. - 力扣(LeetCode)
有两个水壶,容量分别为 x
和 y
升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 target
升。
你可以:
- 装满任意一个水壶
- 清空任意一个水壶
- 将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。
典型的搜索问题,在任意一个时刻,我们可以且仅可以采取以下几种操作:
把 X 壶的水灌进 Y 壶,直至灌满或倒空;
把 Y 壶的水灌进 X 壶,直至灌满或倒空;
把 X 壶灌满;
把 Y 壶灌满;
把 X 壶倒空;
把 Y 壶倒空。
采用深度优先搜索来解决。不过可能会陷入无限递归。需要使用哈希表去重。
using PII = pair<int, int>;class Solution {
public:bool canMeasureWater(int x, int y, int z) {stack<PII> stk;stk.emplace(0, 0);auto hash_function = [](const PII& o) {return hash<int>()(o.first) ^ hash<int>()(o.second);};unordered_set<PII, decltype(hash_function)> seen(0, hash_function);while (!stk.empty()) {if (seen.count(stk.top())) {stk.pop();continue;}seen.emplace(stk.top());auto [remain_x, remain_y] = stk.top();stk.pop();if (remain_x == z || remain_y == z || remain_x + remain_y == z) {return true;}// 把 X 壶灌满。stk.emplace(x, remain_y);// 把 Y 壶灌满。stk.emplace(remain_x, y);// 把 X 壶倒空。stk.emplace(0, remain_y);// 把 Y 壶倒空。stk.emplace(remain_x, 0);// 把 X 壶的水灌进 Y 壶,直至灌满或倒空。stk.emplace(remain_x - min(remain_x, y - remain_y), remain_y + min(remain_x, y - remain_y));// 把 Y 壶的水灌进 X 壶,直至灌满或倒空。stk.emplace(remain_x + min(remain_y, x - remain_x), remain_y - min(remain_y, x - remain_x));}return false;}
};
哈希表存储pair,分别表示x,y壶中的元素。
如果一个类型没有提供哈希函数,那么需要实现一个哈希函数,否则无法存放进对应的桶中,标准库的和一些标量都实现了这个函数所以不需要重载,如果是自定义类型想要存放在桶里必须实现这个函数否则无法正常存放。所以代码中使用lambda表达式定义了哈希函数。
即 auto hash_function = [](const PII& o) {return hash<int>()(o.first) ^ hash<int>()(o.second);};
然后使用 unordered_set<PII, decltype(hash_function)> seen(0, hash_function);定义哈希表。decltype关键字表示自动类型推导。
auto hash_function = [](const PII& o) {return hash()(o.first) ^ hash()(o.second);}; 这行代码定义了一个lambda表达式 hash_function,用于计算PII类型(假设PII是一个具有两个成员变量的结构体或类)的哈希值。这个lambda表达式接受一个PII对象 o 作为输入,并使用 hash() 函数分别计算 o.first 和 o.second 的哈希值,然后使用异或操作符 ^ 结合这两个哈希值。
unordered_set<PII, decltype(hash_function)> seen(0, hash_function); 这行代码创建了一个无序集合 seen,其元素类型为PII,使用之前定义的 hash_function 作为哈希函数。第一个模板参数指定集合中元素的类型为PII,而第二个模板参数 decltype(hash_function) 指定了哈希函数类型,即使用之前定义的 hash_function。
注意,这里的 0 是作为集合的初始容量传递的,表示集合的初始大小为0。
因此,这段代码的目的是创建一个无序集合 seen,用于存储PII类型的对象,并使用自定义的哈希函数来计算元素的哈希值。这样可以在集合中快速查找、插入和删除元素,并确保元素的唯一性。