倒水问题
“fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。
Input
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
Output
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
解题思路
倒水问题的解法有很多,但接下来探讨的是利用广度优先搜索算法去解决问题。其实我最开始看题想到的是来自离散数学里的例子——人、狼、羊、菜过河问题(大家感兴趣可以自己查阅),去建立不同河岸状态的关系图,哪两种状态之间可以互相转换。倒水为题也是这样,他的状态之间的转换方式有6中,fill A,fill B,pour A B,pour B A,empty A,empty B。遍历的就是杯子里所装水的状态,想清楚这些bfs就很好实现了。(注意答案不唯一)
#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
struct cup//记录状态结构体
{
int A, B;//容量为A,B罐子水含量
cup(const int& _A,const int& _B):
A(_A),B(_B){}
};
int ab[1001][1001],pre[1001][1001];
//数组ab存有什么状态转移过来,pre存有什么方式转移过来的
void Print(int &x, int &y, int &B)//输出
{
int a = x, b = y;
vector<int>ans;
while (ab[a][b] != a * B + a + b)
{
int ta = ab[a][b] / (B + 1), tb = ab[a][b] % (B + 1);
ans.push_back(pre[a][b]);
a = ta; b = tb;
}
for(int i=ans.size()-1;i>=0;i--)
switch (ans[i])
{
case 0:
printf("fill A\n");
break;
case 1:
printf("fill B\n");
break;
case 2:
printf("pour A B\n");
break;
case 3:
printf("pour B A\n");
break;
case 4:
printf("empty A\n");
break;
default:
printf("empty B\n");
break;
}
printf("success\n");
}
void bfs(int& A, int& B, int& C)//广度优先搜索
{
queue<cup>q;
q.push(cup(0, 0));
for(int i=0;i<=A;i++)
for(int j=0;j<=B;j++)
ab[i][j]=-1;
ab[0][0] = 0;
while (!q.empty())
{
cup now = q.front();
q.pop();
int a = now.A, b = now.B;
for (int i = 0; i < 6; i++)
{
int x=-1, y=-1;
if (0 == i && a < A && -1 == ab[A][b])
{
x = A; y = b;
}
if (1 == i && b < B && -1 == ab[a][B])
{
x = a; y = B;
}
if (2 == i && b < B && a>0)
{
if (a > B - b && -1==ab[a-B+b][B])
{
x = a - B + b; y = B;
}
if (a < B - b && -1 == ab[0][b + a])
{
x = 0; y = b + a;
}
}
if (3 == i && a < A && b>0)
{
if (b > A - a && -1 == ab[A][b-A+a])
{
y = b - A + a; x = A;
}
if (b < A - a && -1 == ab[b+a][0])
{
y = 0; x = b + a;
}
}
if (4 == i && -1 == ab[0][b])
{
x = 0; y = b;
}
if (5 == i && -1 == ab[a][0])
{
x = a; y = 0;
}
if (x != -1 && y != -1)
{
pre[x][y] = i;
ab[x][y] = a * B + a + b;
if (x == C || y == C)//罐子中包含C单位的水,结束搜索
{
Print(x, y, B);
return;
}
q.push(cup(x, y));
}
}
}
}
int main()
{
int A, B, C;
while (scanf("%d%d%d", &A, &B, &C) != EOF)
if (0 == C)printf("success\n");
else bfs(A,B,C);
return 0;
}