题目描述
倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空
样例
样例输入
2 7 5
2 7 4
样例输出
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
思路
建立状态结构体,包含当前A、B两个杯子中的水量,该状态为第几次操作,前一状态得到现在状态使用的操作,以及操作对应的序号(操作和序号的对应关系也可以用map来映射orz)
本题主要采用BFS,和迷宫有异曲同工之处,每次操作有六种选择:倒空A、倒空B、将A倒入B、将B倒入A、倒满A、倒满B,vis[][]数组用来表示该状态是否出现过,从(0,0)开始入队,BFS,对每个状态都进行六种操作并入队,并将该状态标记为已出现,直到出现目标水量。
输出采用递归判断当前状态是否为初始状态,依次输出。
总结
本题主要思路还是采取BFS,但是对六种选择进行操作时,需要注意A向B倒水以及B向A倒水时,需要判断水量是否能全部转移或者出现容量<水量的情况。
代码
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
struct node
{
int x,y;
int step,pre,op;
};
string operation[6]={"fill A","fill B","empty A","empty B","pour A B","pour B A"};
struct node queue[1000000];
int vis[1000][1000];
int front,rear;
int a,b,c;
void add(int xn,int yn,int stepn,int pre,int op)//入队
{
if(vis[xn][yn]==1)
return;
vis[xn][yn]=1;
queue[++rear].x=xn;
queue[rear].y=yn;
queue[rear].pre=pre;
queue[rear].step=stepn+1;
queue[rear].op=op;
}
void print(int x)//打印步骤
{
if(x==1)
return;
print(queue[x].pre);
cout<<operation[queue[x].op]<<endl;
}
void printAns(int x)//打印最终结果
{
print(x);
cout<<"success"<<endl;
}
void bfs()
{
queue[++front].x=0;
queue[front].y=0;
queue[front].step=0;
queue[front].pre=1;
vis[0][0]=1;
while(front<=rear)
{
int x1=queue[front].x;
int y1=queue[front].y;
int step1=queue[front].step;
if(y1==c)
{
printAns(front);
return;
}
add(a,y1,step1,front,0);//fill A
add(x1,b,step1,front,1);//fill B
add(0,y1,step1,front,2);//empty A
add(x1,0,step1,front,3);//empty B
int sub=min(x1,b-y1);
add(x1-sub,y1+sub,step1,front,4);//pour A B
sub=min(y1,a-x1);
add(x1+sub,y1-sub,step1+1,front,5);//pour B A
front++;
}
}
int main()
{
// int a,b,c;
while(cin>>a>>b>>c)
{
memset(vis,0,sizeof(vis));
front=0;
rear=1;
bfs();
}
}