题目链接
水壶问题
题目描述
注意点
- 1 <= x, y, target <= 1000
解答思路
- 首先想到的是深度优先遍历,对于任意一个状态,可以有以下六种操作:
- 将x水壶中的水倒空
- 将y水壶中的水倒空
- 将x水壶灌满
- 将y水壶灌满
- 将x水壶中的水倒给y水壶,直到x倒空或y灌满为止
- 将y水壶中的水倒给x水壶,直到y倒空或x灌满为止
- 需要注意的是进行上述六种操作时很容易到达同一个状态,导致相同状态遍历多次甚至死循环,所以还需要存储已经遍历过的状态
代码
class Solution {
public boolean canMeasureWater(int x, int y, int target) {
boolean[][] isVisited = new boolean[x + 1][y + 1];
return dfs(x, y, 0, 0, target, isVisited);
}
public boolean dfs(int x, int y, int remain_x, int remain_y, int target, boolean[][] isVisited) {
if (remain_x + remain_y == target) {
return true;
}
if (isVisited[remain_x][remain_y]) {
return false;
}
isVisited[remain_x][remain_y] = true;
// 倒空x
if (dfs(x, y, 0, remain_y, target, isVisited)) {
return true;
}
// 倒空y
if (dfs(x, y, remain_x, 0, target, isVisited)) {
return true;
}
// 灌满x
if (dfs(x, y, x, remain_y, target, isVisited)) {
return true;
}
// 灌满y
if (dfs(x, y, remain_x, y, target, isVisited)) {
return true;
}
// 将x倒给y
if (dfs(x, y, remain_x - Math.min(remain_x, y - remain_y), remain_y + Math.min(remain_x, y - remain_y), target, isVisited)) {
return true;
}
// 将y倒给x
if (dfs(x, y, remain_x + Math.min(remain_y, x - remain_x), remain_y - Math.min(remain_y, x - remain_x), target, isVisited)) {
return true;
}
return false;
}
}
关键点
- 深度优先遍历的思想
- 将水壶x中的水倒给水壶y时,应该将x倒空或将y倒满即可,也就是在进行操作后,水壶x中没水或者水壶y中装满水,水的总量不变,都是remain_x + remain_y