题目链接:http://poj.org/problem?id=1606
题目大意:有A,B两个水壶和无限的水,可以通过6种操作使得B水壶的水量刚好为N,输出满足题意的任意一种操作顺序。
六种操作:
①把A水壶加满
②把B水壶加满
③把A水壶的水全部倒掉
④把B水壶的水全部倒掉
⑤把A水壶里的水全部倒入B水壶中,溢出的水留在A水壶内
⑥把B水壶里的水全部倒入B水壶中,溢出的水留在B水壶内
题目思路:通过6种操作不断尝试使得,B水壶的水恰好等于N。利用宽度优先搜索,记录A和B内的水量的状态,对每种状态执行6种操作,出现过的状态不必再执行(没有意义),每次之前操作需要记录之前的操作,可以用指针来记录。当B水量等于N时,宽度优先搜索结束。记录的操作是反的,因此可以用一个stack来存,最后打印stack内的元素。
注意:利用指针记录地址,不要直接new,定义一个数组,取它的地址就行了,避免内存浪费。
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 1e5+10;
const int CAP = 1010;
struct node{
int a,b;//A水壶和B水壶现在的水量
int op;//现在需要执行操作
node* pre;//记录上一次操作
};
int vis[CAP][CAP];
queue<node> q;
stack<int> s;
node tree[MAXN];
int n,a,b;
node* bfs(){
memset(vis,0,sizeof(vis));
for(int i=0;i<MAXN;i++)
tree[i].pre=NULL;
//初始时A和B内水都是0,需要执行6种操作
while(!q.empty()) q.pop();
tree[0]=(node){0,0,1,NULL};
tree[1]=(node){0,0,2,NULL};
tree[2]=(node){0,0,3,NULL};
tree[3]=(node){0,0,4,NULL};
tree[4]=(node){0,0,5,NULL};
tree[5]=(node){0,0,6,NULL};
q.push(tree[0]);
q.push(tree[1]);
q.push(tree[2]);
q.push(tree[3]);
q.push(tree[4]);
q.push(tree[5]);
int cnt=5;
while(!q.empty()){
node now=q.front();
++cnt;
tree[cnt]=q.front();
q.pop();
node next;
//取地址
next.pre=&tree[cnt];
next.a=now.a;next.b=now.b;
if(now.b==n)
return &tree[cnt];
if(now.op==1)
next.a=a;
else if(now.op==2)
next.b=b;
else if(now.op==3)
next.a=0;
else if(now.op==4)
next.b=0;
else if(now.op==5){
//pour A to B
if(now.b!=b){
//B水壶的水溢出了
if(now.a+now.b>b){
next.b=b;
next.a=now.a+now.b-b;
}else{
next.b=now.a+now.b;
next.a=0;
}
}
}else if(now.op==6){
//pour B to A
if(now.a!=a){
//A水壶的水溢出了
if(now.a+now.b>a){
next.a=a;
next.b=now.a+now.b-a;
}else{
next.a=now.a+now.b;
next.b=0;
}
}
}
//执行六种操作
for(int i=1;i<=6;i++){
if(!vis[next.a][next.b]){
q.push((node){next.a,next.b,i,next.pre});
}
}
//出现过的状态没必要再执行了
vis[next.a][next.b]=1;
}
}
void myPrint(int i){
if(i==1)
printf("fill A\n");
else if(i==2)
printf("fill B\n");
else if(i==3)
printf("empty A\n");
else if(i==4)
printf("empty B\n");
else if(i==5)
printf("pour A B\n");
else if(i==6)
printf("pour B A\n");
}
int main(){
//freopen("d.txt","r",stdin);
while(~scanf("%d%d%d",&a,&b,&n)){
node* ans=bfs();
while(ans->pre!=NULL){
ans=ans->pre;
s.push(ans->op);
}
while(!s.empty()){
myPrint(s.top());
s.pop();
}
printf("success\n");
}
}