原题链接:
https://leetcode.cn/problems/water-and-jug-problem/description/
完成情况:
解题思路:
这段代码是一个解决水壶问题的解决方案。给定两个水壶的容量x和y,以及目标z,判断是否可以通过操作水壶来得到z升的水。代码中使用了一个栈来模拟操作过程,同时使用一个哈希集合来记录已经遍历过的状态,避免重复计算。
在主要的canMeasureWater方法中,首先将初始状态(0,0)入栈,然后进行循环直到栈为空。在每次循环中,首先判断当前状态是否已经遍历过,如果是则弹出栈顶并继续下一次循环。然后将当前状态弹出栈,并判断是否满足目标条件,如果是则返回true。接着按照题目要求依次模拟六种操作,并将新状态入栈。
hash方法用于将状态数组转换成一个长整型的哈希值,用于在哈希集合中存储和比较状态。
参考代码:
package leetcode板块;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
public class _365水壶问题_情况探讨_dfs {
/**
*
* @param x
* @param y
* @param target
* @return
*/
public boolean canMeasureWater(int x, int y, int target) {
/*
有两个水壶,容量分别为 x 和 y 升。
你可以:
1.装满任意一个水壶
2.清空任意一个水壶
3.将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。
TODO 那么这道题就是遍历所有的情况,并判断能否产生需要的求解
*/
Deque<int []> myStack = new LinkedList<int []>();
myStack.push(new int[]{0,0});
Set<Long> canFind = new HashSet<Long>(); //记录能够产生的所有元素
while (!myStack.isEmpty()){
if (canFind.contains(mapToHash(myStack.peek()))){
//说明本次的迭代会进入循环
myStack.pop();
continue;
}
//寻找没有遇到过的组合数
canFind.add(mapToHash(myStack.peek()));
int [] curElements = myStack.pop(); //栈里面每一个都是一个数组,用于记录两个水壶的当前量
int remind_X = curElements[0],remind_y = curElements[1];
//判断当前的所有组合情况,并将所有组合结果保存到栈中
if (remind_X == target || remind_y == target || remind_X + remind_y == target){
return true;
}
//----------将上述相互灌水壶的各种结果值保存在栈中--------------------------------------
//将x灌满
myStack.push(new int[]{x,remind_y});
//将y灌满
myStack.push(new int[]{remind_X,y});
//将x倒空
myStack.push(new int[]{0,remind_y});
//将y倒空
myStack.push(new int[]{remind_X,0});
//将x的水全部倒入y中,直到遇到灌满或倒空。
myStack.push(new int[]{remind_X - Math.min(remind_X,y - remind_y),remind_y + Math.min(remind_X,y-remind_y)});
//将y的水全部倒入x中,直到遇到灌满或倒空。
myStack.push(new int[]{remind_X + Math.min(remind_y,x - remind_X),remind_y - Math.min(remind_y,x-remind_X)});
}
return false;
}
/**
* 防止计算超时,将所有的数都有使用到curElements[0]和curElements[1]去隐射到hash上
* @param curElements
* @return
*/
private Long mapToHash(int[] curElements) {
//return (long)curElements[0]*1000001 + curElements[1];
//1 <= x, y, target <= 10^3
return Long.valueOf(curElements[0]*1000002 + curElements[1]);
}
}