专题一 简单搜索 Problem M

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495

题目大意:一瓶可乐容量为s,两个杯子容量分别为a,b。问能不能通过互相倒可乐把该s容量的可乐平均分开。

解题思路:bfs搜索。

     将三杯可乐看成是一个状态。

     用一个结构体描述一个状态,初始状态为(0,0,s),将其放入队列。

     每次拿出一个点,向6个方向开始扩展。a->b,a->s,b->a,b->s,s->a,s->b。

     如果扩展完的状态满足,则步数加一,标记,放入队尾。一直循环。

     如果取出队首的点的状态满足条件,则输出。如果循环完了也没有找到,则直接输出NO。

代码如下:

  1 #include<cstdio>
  2 #include<queue>
  3 #include<cstring>
  4 using namespace std;
  5 
  6 int s,a,b;
  7 struct Point
  8 {
  9     int a,b,s,step;//描述一个状态(第一杯容量,第二杯容量,第三杯容量,到达该状态所走过的步数)
 10 };
 11 bool vis[105][105][105];//标记该状态是否走过
 12 
 13 void bfs()
 14 {
 15     memset(vis,0,sizeof(vis));//初始化均为走过
 16     queue<Point> q;//创建队列
 17     while(!q.empty())//清空队列
 18     {
 19         q.pop();
 20     }
 21 
 22     Point x,y,temp;
 23     //描述队首
 24     temp.a=0;
 25     temp.b=0;
 26     temp.s=s;
 27     temp.step=0;
 28     q.push(temp);//将第一点放入队首
 29 
 30     while(!q.empty())
 31     {
 32         x=q.front();//从队首取出一点x
 33         q.pop();//删除队首
 34         vis[x.a][x.b][x.s]=1;//标记该点
 35 
 36         if( (x.a==s/2&&x.b==s/2) || (x.a==s/2&&x.s==s/2) || (x.b==s/2&&x.s==s/2) )//如果已经达到预期结果,输出总步数
 37         {
 38             printf("%d\n",x.step);
 39             return;
 40         }
 41 
 42         if(x.s!=0)//从s杯开始扩展
 43         {
 44             if(x.s<a-x.a)//s杯向a杯倒,y为x的下一个状态
 45             {
 46                 y.s=0;
 47                 y.a=x.a+x.s;
 48                 y.b=x.b;
 49                 y.step=x.step+1;
 50             }
 51             else
 52             {
 53                 y.s=x.s-(a-x.a);
 54                 y.a=a;
 55                 y.b=x.b;
 56                 y.step=x.step+1;
 57             }
 58             if(vis[y.a][y.b][y.s]==0)
 59             {
 60                 vis[y.a][y.b][y.s]=1;
 61                 q.push(y);
 62             }
 63 
 64             if(x.s<b-x.b)//s杯向b杯倒,y为x的下一个状态
 65             {
 66                 y.s=0;
 67                 y.a=x.a;
 68                 y.b=x.b+x.s;
 69                 y.step=x.step+1;
 70             }
 71             else
 72             {
 73                 y.s=x.s-(b-x.b);
 74                 y.a=x.a;
 75                 y.b=b;
 76                 y.step=x.step+1;
 77             }
 78             if(vis[y.a][y.b][y.s]==0)
 79             {
 80                 vis[y.a][y.b][y.s]=1;
 81                 q.push(y);
 82             }
 83         }
 84 
 85         if(x.a!=0)//从a杯开始扩展
 86         {
 87             if(x.a<s-x.s)//a杯向s杯倒,y为x的下一个状态
 88             {
 89                 y.a=0;
 90                 y.b=x.b;
 91                 y.s=x.s+x.a;
 92                 y.step=x.step+1;
 93             }
 94             else
 95             {
 96                 y.a=x.a-(s-x.s);
 97                 y.b=x.b;
 98                 y.s=s;
 99                 y.step=x.step+1;
100             }
101             if(vis[y.a][y.b][y.s]==0)
102             {
103                 vis[y.a][y.b][y.s]=1;
104                 q.push(y);
105             }
106 
107             if(x.a<b-x.b)//a杯向b杯倒,y为x的下一个状态
108             {
109                 y.a=0;
110                 y.b=x.b+x.a;
111                 y.s=x.s;
112                 y.step=x.step+1;
113             }
114             else
115             {
116                 y.a=x.a-(b-x.b);
117                 y.b=b;
118                 y.s=x.s;
119                 y.step=x.step+1;
120             }
121             if(vis[y.a][y.b][y.s]==0)
122             {
123                 vis[y.a][y.b][y.s]=1;
124                 q.push(y);
125             }
126         }
127 
128         if(x.b!=0)//从b杯开始扩展
129         {
130             if(x.b<a-x.a)//b杯向a杯倒,y为x的下一个状态
131             {
132                 y.a=x.a+x.b;
133                 y.b=0;
134                 y.s=x.s;
135                 y.step=x.step+1;
136             }
137             else
138             {
139                 y.a=a;
140                 y.b=x.b-(a-x.a);
141                 y.s=x.s;
142                 y.step=x.step+1;
143             }
144             if(vis[y.a][y.b][y.s]==0)
145             {
146                 vis[y.a][y.b][y.s]=1;
147                 q.push(y);
148             }
149 
150             if(x.b<s-x.s)//b杯向s杯倒,y为x的下一个状态
151             {
152                 y.a=x.a;
153                 y.b=0;
154                 y.s=x.s+x.b;
155                 y.step=x.step+1;
156             }
157             else
158             {
159                 y.a=x.a;
160                 y.b=x.b-(s-x.s);
161                 y.s=s;
162                 y.step=x.step+1;
163             }
164             if(vis[y.a][y.b][y.s]==0)
165             {
166                 vis[y.a][y.b][y.s]=1;
167                 q.push(y);
168             }
169         }
170     }
171     printf("NO\n");//如果搜不到满足的条件,说明不可能出现。
172 }
173 
174 int main()
175 {
176     while(scanf("%d %d %d",&s,&a,&b)!=EOF)
177     {
178         if(s==0 && a==0 && b==0) break;
179 
180         if(s%2==1)//剪枝。总容量为奇数时肯定不可能平均分开
181             printf("NO\n");
182         else
183             bfs();
184     }
185     return 0;
186 }
View Code

 

你可能感兴趣的:(专题一 简单搜索 Problem M)