Pots POJ - 3414【状态转移bfs+回溯】

典型的倒水问题:

即把两个水杯的每种状态视为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 }
View Code

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12002682.html
今日推荐