方法1:BFS,C++版本写起来很繁琐,Python很简洁
using PII = pair<int, int>; //分别是x, y中的水量,作为状态量
class Solution {
public:
PII op(int index, const PII& cur, int x, int y) {
switch (index) {
case 0: return make_pair(cur.first, 0);
case 1: return make_pair(cur.first, y);
case 2: return make_pair(0, cur.second);
case 3: return make_pair(x, cur.second);
case 4:
if(cur.first + cur.second > x)
return make_pair(x, cur.first + cur.second - x);
else
return make_pair(cur.first + cur.second, 0);
case 5:
if(cur.first + cur.second > y)
return make_pair(cur.first + cur.second - y, y);
else
return make_pair(0, cur.first + cur.second);
}
return make_pair(0, 0);
}
bool canMeasureWater(int x, int y, int z) {
//BFS依赖一个队列,初始起点为(0,0)
deque<PII> que;
que.emplace_back(make_pair(0, 0));
//哈希表存储访问过的节点
auto hash_func = [](const PII& o) {return hash<int>()(o.first) ^ hash<int>()(o.second); };
unordered_set<PII, decltype(hash_func)> visited(0, hash_func);
while(!que.empty()) {
PII cur = que.front();
que.pop_front();
auto [remain_x, remain_y] = cur;
if(remain_x==z || remain_y==z || remain_x+remain_y==z) {
return true;
}
//BFS:访问当前节点周围的6个节点
for(int i = 0; i < 6; i++) {
PII temp = op(i, cur, x, y);
if(!visited.count(temp)) {
visited.emplace(temp);
que.emplace_back(temp);
}
}
}
return false;
}
};
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
from collections import deque
que = deque()
que.append((0, 0))
visited = set()
visited.add((0, 0))
while que:
cur_x, cur_y = que.popleft();
if cur_x == z or cur_y == z or cur_x + cur_y == z:
return True
for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
(x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
(cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
if (nb_x, nb_y) not in visited:
visited.add((nb_x, nb_y))
que.append((nb_x, nb_y))
return False
方法2:DFS
最大的区别在于visited的处理, 对于没有visited过的节点的临近节点再压入栈,这才符合DFS的思想。
Bug1:for循环放在了if语句的外面。Bug2:visited一开始把原始节点标记为访问,就无法进行DFS了
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
stack = []
stack.append((0, 0))
visited = set()
# visited.add((0, 0))
while stack:
cur_x, cur_y = stack.pop()
if cur_x == z or cur_y == z or cur_x + cur_y == z:
return True
if (cur_x, cur_y) not in visited:
visited.add((cur_x, cur_y))
for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
(x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
(cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
stack.append((nb_x, nb_y))
return False
递归写法,会因为递归层数太深报错:
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
# import sys
# sys.setrecursionlimit(100000)#设置最大递归次数
visited = set()
def DFS(cur_x, cur_y):
if cur_x == z or cur_y == z or cur_x + cur_y == z:
return True
if (cur_x, cur_y) not in visited:
visited.add((cur_x, cur_y))
for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
(x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
(cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
if (nb_x, nb_y) not in visited:
visited.add((nb_x, nb_y))
if DFS(nb_x, nb_y):
return True
visited.remove((nb_x, nb_y))
return False
return DFS(x, y)
方法3:贝祖定理
class Solution {
public:
bool canMeasureWater(int x, int y, int z) {
if(z == 0) return true;
if(x+y < z) return false;
if(x==0 || y==0) return (x+y==z);
return z % gcd(x, y) == 0;
}
};