当前位置: 代码迷 >> 综合 >> poj1606 Jugs(BFS)
  详细解决方案

poj1606 Jugs(BFS)

热度:9   发布时间:2023-12-07 01:19:56.0

题目链接: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 Bif(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 Aif(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");}
}