大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
Input
三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。
Output
如果能平分的话请输出最少要倒的次数,否则输出"NO"。
Sample Input
7 4 3
4 1 3
0 0 0
Sample Output
NO
3
题意:
三个杯子已知容量,只有一杯可乐,来回倒,问多少次能把可乐均分成两份
题意很简单的,关键是思路
思路:
倒的过程只有六种,即6个方向,要求的操作数类似于其他bfs要求的步数
把题中的s n m用数组存,来回倒的过程就能用里外两个循环写,方便一点
代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 int b[5]; 6 struct node 7 { 8 int a[5]; 9 int step; 10 } str[1005], x, y; 11 int vis[105][105][105]; 12 13 void bfs(int s) 14 { 15 if(s%2!=0) printf("NO "); 16 else if(b[1]==s/2) printf("1 "); 17 else 18 { 19 int i, j, in, out; 20 in = 0; 21 out = 0; 22 x.a[0] = s; 23 x.a[1] = 0; 24 x.a[2] = 0; 25 x.step = 0; 26 str[in++] = x; 27 while(in>out) 28 { 29 x = str[out++]; //得到最末尾的一个状态 30 for(i=0; i<3; i++) //x.a[i]往外倒 31 { 32 if(x.a[i]==0) continue; //有的倒 33 for(j=0; j<3; j++) //x.a[j]往里接 34 { 35 if(i==j) continue; //不能一个杯子操作!(一开始这里也没写,样例能过,但是代码不对) 36 y = x; 37 if(x.a[i]+x.a[j] >= b[j]) //能倒满 38 { //注意里面式子都是不能倒过来的 39 y.a[i] = x.a[i] + x.a[j] - b[j]; 40 y.a[j] = b[j]; 41 } 42 else //不能倒满 43 { 44 y.a[j] = x.a[i] + x.a[j]; 45 y.a[i] = 0; 46 } 47 if(vis[y.a[0]][y.a[1]][y.a[2]]==0) //如果这个状态是新的,判断+进队列 48 { 49 y.step++; 50 if((y.a[0]==b[0]/2&&y.a[1]==b[0]/2) //一开始把判断写在判断上面的x了, 51 //每次判断最后一个,超时了。应该是得到一个状态就判断 52 //避免后知后觉做了一些无谓的动作 53 ||(y.a[0]==b[0]/2&&y.a[2]==b[0]/2) 54 ||(y.a[1]==b[0]/2&&y.a[2]==b[0]/2) 55 ) 56 { 57 printf("%d ", y.step); 58 return; 59 } 60 str[in++] = y; 61 vis[y.a[0]][y.a[1]][y.a[2]] = 1; 62 } 63 } 64 } 65 } 66 printf("NO "); 67 } 68 } 69 70 int main() 71 { 72 while(~scanf("%d %d %d", &b[0], &b[1], &b[2])) 73 { 74 if(!b[0]&&!b[1]&&!b[2]) break; 75 memset(vis, 0, sizeof(vis)); 76 vis[b[0]][0][0] = 1; 77 bfs(b[0]); 78 } 79 return 0; 80 }