问题:我们经常会遇见这些问题比如给你一个容量为5升的杯子和一个容量为3升的杯子,水不限使用,要求精确得到4升水并写出算法。
回答:1) 直接以简答的方式给定方案
这个比较简单,即便是不知道什么原理,也可以很快凑出来。假设两个杯子分别为x 5升杯, y 3升杯 : 装满 x ; x -> y ;清空Y ;x -> y ;装满 x ;x -> y
解决方案会有多个,写出一个即可。
2) 编程实现
解法也比较多,我首先想到的DFS(深度优先)搜索,每次我们有6种选择,只要不断的尝试下去,总可以搜索完所有的状态,找到一个解。也可以用宽度优先搜索(BFS)。
使用DFS搜索实现的Java代码:
/**
* @author coder
* @copyright www.acmerblog.com
*/
public class PourWater {
//所有的6中操作。
static String operations[] = {" 装满 x ", " 装满 y "," 清空X ", " 清空Y ", " x -> y ", " y -> x "};
static Stack<Integer> stack = new Stack<Integer>();
static int L1,L2 ;//两个杯子的容量
static int target; //目标容量
static int len;
//防止重复搜索
static boolean dp[][] ;
public static void dfs(int x,int y){
if(dp[x][y]) return;
dp[x][y] = true;
//找到解决方案
if(x == target || y == target){
System.out.println("dfs方法 一个倒水方案:");
for(int oper:stack)
System.out.println(operations[oper]);
return;
}
stack.push(0);
dfs(L1,y);
stack.pop();
stack.push(1);
dfs(x,L2);
stack.pop();
stack.push(2);
dfs(0,y);
stack.pop();
stack.push(3);
dfs(x,0);
stack.pop();
//x向y倒水
stack.push(4);
if(x >= (L2-y) ) //x倒不完,还有剩余
dfs(x - (L2-y),L2);
else
dfs(0 ,y + x); //x没有剩余
stack.pop();
//y向x倒水,需要判断能否倒完
stack.push(5);
if(y >= (L1-x))
dfs(L1,y - (L1-x));
else
dfs(0,y + x);
stack.pop();
}
public static void main(String[] args) {
L1 = 5;
L2 = 3;
target = 4;
len = Math.max(L1, L2) + 1;
dp = new boolean[len][len];
dfs(0,0);
}
}