HDU1495 非常可乐
解题思路:简单的宽搜,见代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 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<node> 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; //若没有符合条件的,则返回-1 51 } 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 }