解题思路:简单的宽搜,见代码:
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 const int maxn = 105; 7 int S, n, m, cap[3], vis[maxn][maxn]; 8 9 struct node{10 int v[3];//每个子装的水11 int cnt; //倒水的次数12 bool friend operator < (node A, node B){13 return A.cnt > B.cnt; //cnt越小,优先级越高14 }15 }s, e;16 17 priority_queue q; //优先队列18 19 int bfs()20 {21 while(!q.empty()) q.pop();22 q.push(s);23 24 while(!q.empty())25 {26 s = q.top(); q.pop();27 // printf("s.cnt = %d\n", s.cnt); //太大意,因为这行没注释,WA了一发28 29 //n杯子和s杯子各有一半可乐时返回倒水次数30 if(s.v[0] == S / 2 && s.v[2] == S / 2) return s.cnt;31 32 //i杯子往j杯子里面倒水33 for(int i = 0; i < 3; i++)34 for(int j = 0; j < 3; j++)35 {36 if(i == j) continue; //不能往自己的杯子倒水37 //如果i杯子是空的或者j杯子已满,则不用倒水38 if(s.v[i] == 0 || s.v[j] == cap[j]) continue;39 40 int t = min(s.v[i], cap[j] - s.v[j]); //自己思考这一步41 e = s; //这步不能忘了42 e.v[i] = s.v[i] - t, e.v[j] = s.v[j] + t, e.cnt = s.cnt + 1;43 if(!vis[e.v[0]][e.v[1]]) //没访问过44 {45 vis[e.v[0]][e.v[1]] = 1; //标记为已经访问46 q.push(e);47 }48 }49 }50 return -1; //若没有符合条件的,则返回-151 }52 53 int main()54 {55 while(~scanf("%d %d %d", &S, &n, &m) && (S || n || m))56 {57 if(S % 2) //s为奇数,则不可能均分58 {59 printf("NO\n");60 continue;61 }62 63 if(n == m) //n等于m时,直接把一个杯子倒满即可64 {65 printf("1\n");66 continue;67 }68 int tmp;69 //初始化n为更大的杯子70 if(m > n) tmp = n, n = m, m = tmp;71 memset(vis, 0, sizeof(vis));72 73 cap[0] = n, cap[1] = m, cap[2] = S;74 s.v[0] = 0, s.v[1] = 0, s.v[2] = S, s.cnt = 0;75 vis[0][0] = 1; 76 77 int ans = bfs();78 79 if(ans == -1) printf("NO\n");80 else printf("%d\n", ans);81 }82 return 0;83 }