题意:
倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。现有A,B容量的杯子和饮水机,通过有限步骤的倒水,得到容量为c的水。
输入:
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质
输出:
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
思路:
分析这道题的初始状态是A,B中的会都是0,现要得到c容量的水即A或者B杯子中有一个杯子中的水的容量是c即可。中间有限次步骤可以是fill A,fill B,empty A,empty B,pour A B,pour B A,这样每次中间杯子中的状态值都是以上步骤导致的,所以把A,B中的容量(x,y)作为状态点,从初始(0,0)到最终状态点(0,y)或者(x,0),这时就可以用bfs进行广搜,中间状态通过对(x,y)进行六种步骤中未进行过的一个生成状态。特判就是x等于0或者是y等于0,然后对六种步骤的每一个求出一个(x,y),如果(x,y)未进行过(没有被标记),就选择放入队列,直到队列为空或者到达最终状态。
总结:
这是隐式图问题,利用bfs做,主要难点是找出中间节点(状态),题目中隐式给出了每一种可走的方案,要根据可走的方案得出每一个可行的中间状态(点)。
代码:
/*
对于状态值status
可以用map来记录每个状态点的前驱(用来输出路径) map<status,status>
map也可以用来标记是否到过 map<status,bool>
开始状态0,0 容量A,B,C 结束状态A杯子中=c||B杯子中=c
*/
#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;
int A,B,C;
struct point
{
int x,y;
point(){}
point(int _x,int _y)
{
x=_x;y=_y;
}
bool operator<(const point &a)const
{
return x == a.x ? y < a.y : x < a.x;
}
bool operator==(const point &a)const
{
return x == a.x && y == a.y;
}
point ATOB()
{
point c;c.x=max(x+y-B,0);c.y=min(B,x+y);return c;
}
point BTOA()
{
point c;c.x=min(A,x+y);c.y=max(0,x+y-A); return c;
}
point FILLA()
{
return point(A,y);
}
point FILLB()
{
return point(x,B);
}
point EMPTYA()
{
return point(0,y);
}
point EMPTYB()
{return point(x,0);
}
};
map<point,bool> flag;
map<point,point>path;
map<point,string>ppath;
queue<point> q;
void turn(point x,point y,string str)
{
if(!flag[y])
{
flag[y]=1;path[y]=x;ppath[y]=str;q.push(y);
}
}
void print(point ed)
{
if(ed.x==0&&ed.y==0) return;
print(path[ed]);
cout<<ppath[ed]<<endl;
}
void bfs(int x,int y)
{
point source(x,y);q.push(source); flag[source]=1;
while(!q.empty())
{
point now=q.front();q.pop();
if(now.x==C||now.y==C)
{
print(now);return;
}
turn(now,now.ATOB(),"pour A B");
turn(now,now.BTOA(),"pour B A");
turn(now,now.FILLA(),"fill A");
turn(now,now.FILLB(),"fill B");
turn(now,now.EMPTYA(),"empty A");
turn(now,now.EMPTYB(),"empty B");
}
}
int main()
{
while(cin>>A>>B>>C)
{ flag.clear();path.clear();ppath.clear();
while (!q.empty())q.pop();//对于每一组进行情况
bfs(0,0);cout<<"success"<<endl;
} return 0;
}