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 }

原文地址:https://www.cnblogs.com/1024-xzx/p/12002682.html

时间: 2024-11-09 04:55:25

Pots POJ - 3414【状态转移bfs+回溯】的相关文章

POJ 3984-迷宫问题--BFS+回溯路径

迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7862   Accepted: 4615 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要

poj 1324 状态压缩+bfs

http://poj.org/problem?id=1324 Holedox Moving Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17042   Accepted: 4065 Description During winter, the most hungry and severe time, Holedox sleeps in its lair. When spring comes, Holedox wakes

Pots POJ - 3414 (搜索+记录路径)

Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22688   Accepted: 9626   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        f

POJ 1163 状态转移

The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39013   Accepted: 23422 Description 73 88 1 02 7 4 44 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on

POJ 3414 Pots (经典bfs )

Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap; DROP(i)      empty the pot i to the drain; POUR(i,j)    pour from

POJ 3414 Pots(罐子)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

广搜+输出路径 POJ 3414 Pots

POJ 3414 Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13547   Accepted: 5718   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)

POJ 2965-The Pilots Brothers&#39; refrigerator--位运算+BFS+回溯路径

The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18576   Accepted: 7108   Special Judge Description The game "The Pilots Brothers: following the stripy elephant" has a quest where a player needs to o

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 #