POJ 3414 Pots
题意:两个容积分别为A,B的杯子可进行以下三种操作:
1、倒满杯子FILL(i)
2、倒空杯子DROP(i)
3、将杯子 i 中的水倒进杯子 j ,倒完后要么 i 为空,要么 j 为满。
问操作多少次能在某只杯子中恰好得到容积为C的水及操作步骤。
分析:广度优先搜索,每次的状态是当前两只杯子分别得水量,及到此状态的操作数。状态转移的方式有:分别倒空/倒满两只,一只倒进另一只,共6种。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <algorithm> 11 using namespace std; 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 struct node 15 { 16 int a,b,t; 17 int r[210];//记录执行的是哪种操作 18 }; 19 bool v[105][105]; 20 int a,b,c; 21 char l[7][15]= {" " , "FILL(1)" , "FILL(2)" , "DROP(1)" , "DROP(2)" , "POUR(1,2)" ,"POUR(2,1)"};//用于打印 22 void bfs() 23 { 24 int i,j; 25 node x,y; 26 queue<node> q; 27 x.a=0;x.b=0;x.t=0; 28 v[x.a][x.b]=1; 29 q.push(x); 30 while(!q.empty()) 31 { 32 y=q.front(); 33 q.pop(); 34 if(y.a==c||y.b==c) 35 { 36 printf("%d\n",y.t); 37 for(i=1;i<=y.t;i++) 38 { 39 printf("%s\n",l[y.r[i]]); 40 } 41 return ; 42 } 43 for(i=1;i<=6;i++) 44 { 45 if(i==1)//第一种方式,倒满A 46 { 47 x.b=y.b; 48 x.a=a; 49 y.r[y.t+1]=1; 50 } 51 if(i==2)//第二种方式,倒满B 52 { 53 x.a=y.a; 54 x.b=b; 55 y.r[y.t+1]=2; 56 } 57 if(i==3)//第三种方式,倒空A 58 { 59 x.b=y.b; 60 x.a=0; 61 y.r[y.t+1]=3; 62 } 63 if(i==4)////第四种方式,倒空B 64 { 65 x.a=y.a; 66 x.b=0; 67 y.r[y.t+1]=4; 68 } 69 if(i==5)//第五种方式,A——>B 70 { 71 if(y.a<b-y.b)A不能倒满B 72 { 73 x.b=y.a+y.b; 74 x.a=0; 75 } 76 else 77 { 78 x.b=b; 79 x.a=y.a+y.b-b; 80 } 81 y.r[y.t+1]=5; 82 } 83 if(i==6)//第六种方式,B——>A 84 { 85 if(y.b<a-y.a)B不能倒满A 86 { 87 x.a=y.a+y.b; 88 x.b=0; 89 } 90 else 91 { 92 x.a=a; 93 x.b=y.b+y.a-a; 94 } 95 y.r[y.t+1]=6; 96 } 97 if(!v[x.a][x.b]) 98 { 99 v[x.a][x.b]=1; 100 x.t=y.t+1; 101 for(j=1;j<=x.t;j++)//将前一步的操作序列复制到本状态本步前 102 { 103 x.r[j]=y.r[j]; 104 } 105 q.push(x); 106 } 107 } 108 } 109 printf("impossible\n");//每种情况都试一遍还不能达到 110 } 111 int main() 112 { 113 int i,j; 114 while(~scanf("%d %d %d",&a,&b,&c)) 115 { 116 memset(v,0,sizeof v); 117 bfs(); 118 } 119 return 0; 120 }