一、问题描述
现有8升、5升、3升的容器各一个,均无任何度量标记,其中8升的容器装满啤酒,其他两个为空。要求用上述容器倒来倒去,分成两份4升的啤酒。
二、解决方法
1.定义状态空间
用(x,y,z)三个有序整数表示状态空间的一个状态, x表示8L瓶中的酒量,x∈[0,8]; y表示5L瓶中的酒量,y∈[0,5]; z表示3L瓶中的酒量,z∈[0,3]; 起始状态为:(8,0,0),目标状态为(4,4,0)
2.确定一组操作
①x倒入y ②x倒入z ③y倒入x ④y倒入z ⑤z倒入x ⑥z倒入y
3.搜索过程
和水壶问题一样,先初始化状态空间,设置第一个节点的状态为已访问,将此节点加入栈中 随后开始深度优先搜索,以当前节点为父节点,遍历其所有的子节点,若该节点没有被访问过则把该节点的状态加入栈中,并且设为已访问,直到寻找到满足最终状态的节点,输出路径 之后重复这个步骤,直到遍历完所有的路径,递归结束
三、代码实现
1.关键代码
实现深度优先搜索
private void solve(int a, int b, int c) {
if (a == 4 && b == 4) {
print(pos);
pos++;
} else {
for (int i = 1; i <= 6; i++) {
WaterState news = operate(a, b, c, i);
if (checkRepeat(news.a, news.b) == 0) {
pathStack.push(news);
space[news.a][news.b] = 1;
solve(news.a, news.b, news.c);
pathStack.pop();
space[news.a][news.b] = 0;
}
}
}
}
2.全部代码
import java.util.Stack;
public class Beer {
private int pos = 1;
private int[][] space = new int[9][6];
private Stack<WaterState> pathStack = new Stack();
public static void main(String[] args) {
Beer beer = new Beer();
}
public Beer() {
initSpace();
int a = 8;
int b = 0;
int c = 0;
pathStack.push(new WaterState(8, 0, 0));
solve(a, b, c);
}
private void print(int pos) {
System.out.println("结果" + pos + ":");
int i = 0;
int l = pathStack.size();
while (l > 0) {
System.out.println(pathStack.get(i).a + " " + pathStack.get(i).b + " " + pathStack.get(i).c);
i++;
l--;
}
System.out.println("操作次数:" + i);
System.out.println();
}
private void solve(int a, int b, int c) {
if (a == 4 && b == 4) {
print(pos);
pos++;
} else {
for (int i = 1; i <= 6; i++) {
WaterState news = operate(a, b, c, i);
if (checkRepeat(news.a, news.b) == 0) {
pathStack.push(news);
space[news.a][news.b] = 1;
solve(news.a, news.b, news.c);
pathStack.pop();
space[news.a][news.b] = 0;
}
}
}
}
private WaterState operate(int a, int b, int c, int i) {
switch (i) {
case 1://a->b
if (a + b >= 5) {
a = a + b - 5;
b = 5;
} else {
b = a + b;
a = 0;
}
break;
case 2://b->c
if (b + c >= 3) {
b = b + c - 3;
c = 3;
} else {
c = b + c;
b = 0;
}
break;
case 3://c->a
a = a + c;
c = 0;
break;
case 4://a->c
if (a + c >= 3) {
a = a + c - 3;
c = 3;
} else {
c = a + c;
a = 0;
}
break;
case 5://b->a
a = a + b;
b = 0;
break;
case 6://c->b
if (b + c >= 5) {
c = b + c - 5;
b = 5;
} else {
b = b + c;
c = 0;
}
break;
}
return new WaterState(a, b, c);
}
private int checkRepeat(int a, int b) {
if (space[a][b] == 1) {
return 1;
}
return 0;
}
private void initSpace() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 6; j++) {
space[i][j] = 0;
}
}
space[8][0] = 1;
}
static class WaterState {
int a, b, c;
WaterState(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
}
4、运行结果
总结
在水壶问题的基础上进行修改,整体思路差差不多 希望对你有所帮助
|