题意:还是倒水问题:给出三个瓶子容积为 A,B,C :A =B+C;然后问倒几次才能够使其中两个瓶子中水相同且平分已有的水。一开始A瓶被装满水
思路:像装水这种操作的问题就是模拟,而dfs能够解决最少操作问题(通过记录操作数)
完整代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; int s[3] , vis[105][105][105]; struct cup{ int v[3] , step; }now; int bfs(){ queue<cup> q ; now.v[0] = s[0] ,now.v[1] = now.v[2] = now.step = 0; vis[now.v[0]][now.v[1]][now.v[2]] = 1; q.push(now); while(!q.empty()){ now = q.front(); if((now.v[0] == now.v[1] && now.v[2] == 0) || (now.v[0] == now.v[2] && now.v[1] == 0) || (now.v[1] == now.v[2] && now.v[0] == 0)) //判断终止条件,即有一个杯子是空,另外两个杯子一样多 { return now.step; } q.pop(); for(int i = 0 ; i < 3 ; i ++){ //模拟倒水的 6 种情况 a 倒 b,c || b倒 a , c || c 倒 a , b for(int j = 0 ; j < 3 ; j ++){ if(i != j){ // 非自己倒给自己的过程,即其他的倒水过程 int k = s[j] - now.v[j]; if(k > now.v[i]){ k = now.v[i]; } cup next = now; //第 i 杯往第 j 杯里倒水过程 next.v[i] = now.v[i] - k; next.v[j] = now.v[j] + k; next.step = now.step + 1; if(vis[next.v[0]][next.v[1]][next.v[2]] == 0){ vis[next.v[0]][next.v[1]][next.v[2]] = 1; q.push(next); } } } } } return -1; } int main(){ while(cin >> s[0] >> s[1] >> s[2] ){ if(!(s[0] + s[1] + s[2])) break; memset(vis,0,sizeof(vis)); if(s[0] != s[1] + s[2]){ printf("NO "); break; } else{ int ans = bfs(); if(ans == -1) printf("NO "); else printf("%d ",ans); } } return 0 ; }