题目:
倒水问题 “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 Out:
putfill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
Notes:
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。
题目分析:
此题为倒水问题,有A,B两个杯子,要倒出容量为C的水,大方面来讲有三种情况,即一个杯子倒空,一个杯子倒满以及从一个杯子倒入另一个杯子中;而细分来讲有八种情况,分别为:
(1)倒空A杯。
(2)倒空B杯。
(3)倒满A杯。
(4)倒满B杯。
(5)当A杯不满且B杯有水的情况,B杯水倒入A杯:
(5.1)A.B水量不大于A杯容量时,倒入后B杯水为0,A杯为A+B的水量。
(5.2)A.B水量大于A杯容量时,倒入后B杯水为A+B的水量减去A的容量,A杯为A的容量。
(6)当B杯不满且A杯有水的情况,A杯水倒入B杯:
(6.1)A.B水量不大于B杯容量时,倒入后A杯水为0,B杯为A+B的水量。
(6.2)A.B水量大于B杯容量时,倒入后A杯水为A+B的水量减去A的容量,B杯为B的容量。
要找出可行的方案,可以采用bfs宽度搜索,亦可以采用dfs深度搜索,此处采用bfs,因为bfs可以找到步骤最少的方案。
首先将每个状态的A,B的水量用结构体node表示,其中node结构体中的status表示该A,B状态是经过什么操作形成的。然后定义一个队列,当队列不为空时,取出队首元素,根据前面分析的倒水的八种情况,将可能的A,B水量情况压入队列之中直到A,B中至少有一个水量刚好等于目标水量C。最后递归输出达到目标水量进行步骤的status即可。
代码:
#include<iostream>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
const int maxn=1e3+5;
struct node
{
int A;
int B;
int status;
bool operator<(const node &s) const
{
return A!=s.A ? A<s.A : B<s.B ;
}
bool operator==(const node &s) const
{
return A == s.A && B == s.B;
}
};
bool vis[maxn][maxn];
node pre[maxn][maxn];
void trans(node tt)
{
switch(tt.status)
{
case 1:
cout<<"fill B"<<endl;
break;
case 2:
cout<<"empty B"<<endl;
break;
case 3:
cout<<"fill A"<<endl;
break;
case 4:
cout<<"empty A"<<endl;
break;
case 5:
cout<<"pour A B"<<endl;
break;
case 6:
cout<<"pour B A"<<endl;
break;
default:
break;
}
}
void output(node tt)
{
if(tt.A!=0||tt.B!=0)
{
output(pre[tt.A][tt.B]);
trans(tt);
}
}
void bfs(int a,int b,int c)
{
queue<node> q;//队列
node s;
node t;
memset(vis,false,sizeof(vis));
memset(pre,0,sizeof(pre));
s.A=s.B=0;//起点两杯水均为空
vis[s.A][s.B]=true;
q.push(s);
while(!q.empty())
{
s=q.front();
q.pop();
if(s.A==c||s.B==c)//完成
{
output(s);
cout<<"success"<<endl;
return ;
}
if(s.B<b)//b中水不满,倒满B杯中的水
{
t.B=b;
t.A=s.A;
if(!vis[t.A][t.B])
{
t.status=1;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
if(s.B>0)//b中有水,倒空B杯中的水
{
t.B=0;
t.A=s.A;
if(!vis[t.A][t.B])
{
t.status=2;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
if(s.A<a)//a中水不满,倒满A杯中的水
{
t.A=a;
t.B=s.B;
if(!vis[t.A][t.B])
{
t.status=3;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
if(s.A>0)//a中有水,倒空a杯中的水
{
t.A=0;
t.B=s.B;
if(!vis[t.A][t.B])
{
t.status=4;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
if(s.A!=0&&s.B<b)//a中有水且b中水不满,考虑a杯倒入b杯
{
if(s.A+s.B<=b)
{
t.B=s.A+s.B;
t.A=0;
if(!vis[t.A][t.B])
{
t.status=5;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
else
{
t.B=b;
t.A=s.B+s.A-b;
if(!vis[t.A][t.B])
{
t.status=5;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
}
if(s.B!=0&&s.A<a)//a中有水且b中水不满,考虑b杯倒入a杯
{
if(s.A+s.B<=a)
{
t.A=s.A+s.B;
t.B=0;
if(!vis[t.A][t.B])
{
t.status=6;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
else
{
t.A=a;
t.B=s.B+s.A-a;
if(!vis[t.A][t.B])
{
t.status=6;
q.push(t);
vis[t.A][t.B]=true;
pre[t.A][t.B]=s;
}
}
}
}
}
int main()
{
int aa,bb,cc;
while(cin>>aa>>bb>>cc)
{
bfs(aa,bb,cc);
}
return 0;
}