一、问题描述
有两个水壶,容量分别为 jug1Capacity
和 jug2Capacity
升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity
升。
如果可以得到 targetCapacity
升水,最后请用以上水壶中的一或两个来盛放取得的 targetCapacity
升水。
你可以:
- 装满任意一个水壶
- 清空任意一个水壶
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例 1:
输入: jug1Capacity = 3, jug2Capacity = 5, targetCapacity = 4 输出: true 解释:来自著名的 "Die Hard"
示例 2:
输入: jug1Capacity = 2, jug2Capacity = 6, targetCapacity = 5 输出: false
示例 3:
输入: jug1Capacity = 1, jug2Capacity = 2, targetCapacity = 3 输出: true
二、解题思路
1.问题分析
- 深度优先搜索
X 壶中的水量, Y 壶中的水量。
在任意一个时刻,我们可以且仅可以采取以下几种操作:
把 X 壶的水灌进 Y 壶,直至灌满或倒空;
把 Y 壶的水灌进 X 壶,直至灌满或倒空;
把 X 壶灌满;
把 Y 壶灌满;
把 X 壶倒空;
把 Y 壶倒空。
2.解题代码
代码如下:
public boolean canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {
if(jug1Capacity + jug2Capacity < targetCapacity){
return false;
}
Map<String, Integer> done = new HashMap<>();
Stack<Pair<Integer, Integer>> stack = new Stack<>();
stack.push(new Pair<Integer, Integer>(0, 0));
while(!stack.isEmpty()){
Pair<Integer, Integer> pair = stack.pop();
Integer left = pair.getKey();
Integer right = pair.getValue();
String mark = left.toString() + "#" + right.toString();
// System.out.println("mark -> " + mark);
if(done.containsKey(mark)){
continue;
}
done.put(mark, 1);
if(left+right == targetCapacity){
return true;
}
stack.push(new Pair<Integer, Integer>(left, 0));
stack.push(new Pair<Integer, Integer>(0, right));
stack.push(new Pair<Integer, Integer>(left, jug2Capacity));
stack.push(new Pair<Integer, Integer>(jug1Capacity, right));
if(left+right>jug1Capacity){
stack.push(new Pair<Integer, Integer>(jug1Capacity, left+right-jug1Capacity));
}else{
stack.push(new Pair<Integer, Integer>(left+right, 0));
}
if(left+right>jug2Capacity){
stack.push(new Pair<Integer, Integer>(left+right-jug2Capacity, jug2Capacity));
}else{
stack.push(new Pair<Integer, Integer>(0, left+right));
}
}
return false;
}