题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103921#problem/M
开始数组是三维210的,MLE,然后超时,stl-queue 改成了数组模拟队列。水题。
1 /* 2 想了想。好像和POJ 3414 差不多。 3 看成是三个容器。初始容量分别是满着,0, 0, 然后问是否有可能两个杯子的水分别是第一个杯子的一半。如果有。输出最短步数。 4 S == N + M.那就是至少两个杯子的容量>= s/2. 5 如果有可能。首先s是偶数。然后,判断的话。好像就只能初始状态往下搜,然后遇到搜完所有的可能还没有就是不可能吧。状态不重复、就没法扩展还是会停止的。 6 */ 7 8 #include <stdio.h> 9 #include <string.h> 10 #include <iostream> 11 #include <queue> 12 #define maxn 1000000 13 using namespace std; 14 15 int s, n, m; 16 17 struct Node { 18 int s, n, m; 19 }que[10000], now, temp; 20 21 int ans; 22 int step[110][110][110]; 23 int vis[110][110][110]; 24 25 bool divide(Node a) { 26 if (a.s == s/2 && a.n == s/2) 27 return true; 28 if (a.s == s/2 && a.m == s/2) 29 return true; 30 if (a.n == s/2 && a.m == s/2) 31 return true; 32 return false; 33 } 34 35 int head, tail; 36 37 void bfs() { 38 while(head < tail) { 39 now = que[head++]; 40 if (divide(now)) { 41 ans = step[now.s][now.n][now.m]; 42 return; 43 } 44 int pour; 45 // 操作数 1.s->n 2.s->m 3.n->m 4.n->s 5.m->n 6.m->s 46 if (now.s > 0 && now.n < n) { 47 pour = min(now.s, n-now.n); 48 temp.s = now.s - pour; 49 temp.n = now.n + pour; 50 temp.m = now.m; 51 52 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 53 que[tail++] = temp; 54 vis[temp.s][temp.n][temp.m] = 1; 55 step [temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 56 } 57 58 } 59 60 if (now.s > 0 && now.m < m) { 61 pour = min(now.s, m-now.m); 62 temp.s = now.s - pour; 63 temp.m = now.m + pour; 64 temp.n = now.n; 65 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 66 que[tail++] = temp; 67 vis[temp.s][temp.n][temp.m] = 1; 68 step[temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 69 } 70 } 71 72 if (now.n > 0 && now.s < s) { 73 pour = min(now.n, s-now.s); 74 temp.s = now.s + pour; 75 temp.n = now.n - pour; 76 temp.m = now.m; 77 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 78 que[tail++] = temp; 79 vis[temp.s][temp.n][temp.m] = 1; 80 step[temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 81 } 82 } 83 84 if (now.n > 0 && now.m < m) { 85 pour = min(now.n, m-now.m); 86 temp.n = now.n - pour; 87 temp.m = now.m + pour; 88 temp.s = now.s; 89 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 90 que[tail++] = temp; 91 vis[temp.s][temp.n][temp.m] = 1; 92 step [temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 93 } 94 } 95 96 if (now.m > 0 && now.s < s) { 97 pour = min(now.m, s-now.s); 98 temp.s = now.s + pour; 99 temp.m = now.m - pour; 100 temp.n = now.n; 101 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 102 que[tail++] = temp; 103 vis[temp.s][temp.n][temp.m] = 1; 104 step [temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 105 } 106 } 107 108 if (now.m > 0 && now.n < n) { 109 pour = min(now.m, n-now.n); 110 temp.n = now.n + pour; 111 temp.m = now.m - pour; 112 temp.s = now.s; 113 if (!vis[temp.s][temp.n][temp.m] && temp.s >= 0 && temp.n >= 0 && temp.m >= 0) { 114 que[tail++] = temp; 115 vis[temp.s][temp.n][temp.m] = 1; 116 step [temp.s][temp.n][temp.m] = step[now.s][now.n][now.m] + 1; 117 } 118 } 119 } 120 } 121 122 int main() { 123 while(~scanf("%d%d%d", &s, &n, &m)) { 124 now.s = s, now.n = 0, now.m = 0; 125 if (s % 2) { 126 printf("NO\n"); 127 continue; 128 } 129 head = 0, tail = 0; 130 memset(step, 0, sizeof(step)); 131 memset(vis, 0, sizeof(vis)); 132 if (s == 0 && n == 0 && m == 0) 133 break; 134 ans = maxn; 135 que[tail++] = now; 136 vis[now.s][now.n][now.m] = 1; 137 step[now.s][now.n][now.m] = 0; 138 139 bfs(); 140 if (ans == maxn) { 141 printf("NO\n"); 142 } 143 else printf("%d\n", ans); 144 } 145 return 0; 146 }