标签:队列 play ems scan gif 路径 回溯 枚举 结构体
典型的倒水问题:
即把两个水杯的每种状态视为bfs图中的点,如果两种状态可以转化,即可认为二者之间可以连一条边。
有3种倒水的方法,对应2个杯子,共有6种可能的状态转移方式。即相当于图中想走的方法有6种,依次枚举即可。
用一个二维数组标记状态,以免重复。
难点在于输出路径,即bfs回溯。
我的处理方法是,在bfs的队列基础上,用一个vector保存每一个可能的状态,即每个状态对应一个编号。同时结构体中不仅保存每个状态的信息,而且还要保存每个状态的对应编号和上一个状态的对应编号。
那么,当bfs到达终点后,就可以从后向前进行回溯,找到路径,然后反向输出即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 int Va,Vb,C; 7 struct pot 8 { 9 int a,b,step,t,my,last; 10 }; 11 bool vis[105][105]; 12 int a[10000]; 13 queue<pot>que; 14 vector<pot>pre; 15 int bfs() 16 { 17 while(!que.empty()) 18 que.pop(); 19 pot s=pot{0,0,-1,0,0,-1}; 20 que.push(s); 21 vis[0][0]=1; 22 pre.push_back(s); 23 while(!que.empty()) 24 { 25 pot now=que.front(); 26 que.pop(); 27 for(int i=0;i<6;i++) 28 { 29 pot tmp=now; 30 if(i==0)//fill(1) 31 tmp.a=Va; 32 else if(i==1)//fill(2) 33 tmp.b=Vb; 34 else if(i==2)//drop(1) 35 tmp.a=0; 36 else if(i==3)//drop(2) 37 tmp.b=0; 38 else if(i==4)//pour(1,2) 39 { 40 if(tmp.a>Vb-tmp.b) 41 { 42 tmp.a-=(Vb-tmp.b); 43 tmp.b=Vb; 44 } 45 else 46 { 47 tmp.b+=tmp.a; 48 tmp.a=0; 49 } 50 } 51 else if(i==5)//pour(2,1) 52 { 53 if(tmp.b>Va-tmp.a) 54 { 55 tmp.b-=(Va-tmp.a); 56 tmp.a=Va; 57 } 58 else 59 { 60 tmp.a+=tmp.b; 61 tmp.b=0; 62 } 63 } 64 if(!vis[tmp.a][tmp.b]) 65 { 66 tmp.step=i; 67 tmp.t=now.t+1; 68 tmp.last=now.my; 69 pre.push_back(tmp); 70 tmp.my=pre.size()-1; 71 vis[tmp.a][tmp.b]=1; 72 que.push(tmp); 73 if(tmp.a==C||tmp.b==C) 74 return tmp.t; 75 } 76 } 77 } 78 return -1; 79 } 80 void print(int u) 81 { 82 if(u==0) 83 printf("FILL(1)\n"); 84 else if(u==1) 85 printf("FILL(2)\n"); 86 else if(u==2) 87 printf("DROP(1)\n"); 88 else if(u==3) 89 printf("DROP(2)\n"); 90 else if(u==4) 91 printf("POUR(1,2)\n"); 92 else if(u==5) 93 printf("POUR(2,1)\n"); 94 } 95 int main() 96 { 97 while(scanf("%d%d%d",&Va,&Vb,&C)!=EOF) 98 { 99 memset(vis,0,sizeof(vis)); 100 pre.clear(); 101 int ans=bfs(); 102 if(ans==-1) 103 printf("impossible\n"); 104 else 105 { 106 printf("%d\n",ans); 107 memset(a,0,sizeof(a)); 108 int p=pre.size()-1; 109 int cnt=0; 110 while(pre[p].last!=-1) 111 { 112 a[++cnt]=pre[p].step; 113 p=pre[p].last; 114 } 115 for(int i=cnt;i>=1;i--) 116 print(a[i]); 117 } 118 } 119 return 0; 120 }
标签:队列 play ems scan gif 路径 回溯 枚举 结构体
原文地址:https://www.cnblogs.com/1024-xzx/p/12002682.html