Jugs
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 4076 | Accepted: 2411 | Special Judge |
Description
In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with the following puzzle. They were given a 3-gallon jug and a 5-gallon jug and were asked to fill the 5-gallon jug with exactly 4 gallons. This problem generalizes that puzzle.
You have two jugs, A and B, and an infinite supply of water. There are three types of actions that you can use: (1) you can fill a jug, (2) you can empty a jug, and (3) you can pour from one jug to the other. Pouring from one jug to the other stops when the first jug is empty or the second jug is full, whichever comes first. For example, if A has 5 gallons and B has 6 gallons and a capacity of 8, then pouring from A to B leaves B full and 3 gallons in A.
A problem is given by a triple (Ca,Cb,N), where Ca and Cb are the capacities of the jugs A and B, respectively, and N is the goal. A solution is a sequence of steps that leaves exactly N gallons in jug B. The possible steps are
fill A
fill B
empty A
empty B
pour A B
pour B A
success
where "pour A B" means "pour the contents of jug A into jug B", and "success" means that the goal has been accomplished.
You may assume that the input you are given does have a solution.
You have two jugs, A and B, and an infinite supply of water. There are three types of actions that you can use: (1) you can fill a jug, (2) you can empty a jug, and (3) you can pour from one jug to the other. Pouring from one jug to the other stops when the first jug is empty or the second jug is full, whichever comes first. For example, if A has 5 gallons and B has 6 gallons and a capacity of 8, then pouring from A to B leaves B full and 3 gallons in A.
A problem is given by a triple (Ca,Cb,N), where Ca and Cb are the capacities of the jugs A and B, respectively, and N is the goal. A solution is a sequence of steps that leaves exactly N gallons in jug B. The possible steps are
fill A
fill B
empty A
empty B
pour A B
pour B A
success
where "pour A B" means "pour the contents of jug A into jug B", and "success" means that the goal has been accomplished.
You may assume that the input you are given does have a solution.
Input
Input to your program consists of a series of input lines each defining one puzzle. Input for each puzzle is a single line of three positive integers: Ca, Cb, and N. Ca and Cb are the capacities of jugs A and B, and N is the goal. You can assume 0 < Ca <= Cb and N <= Cb <=1000 and that A and B are relatively prime to one another.
Output
Output from your program will consist of a series of instructions from the list of the potential output lines which will result in either of the jugs containing exactly N gallons of water. The last line of output for each puzzle should be the line "success". Output lines start in column 1 and there should be no empty lines nor any trailing spaces.
Sample Input
3 5 4 5 7 3
Sample Output
fill B pour B A empty A pour B A fill B pour B A success fill A pour A B fill A pour A B empty B pour A B success
1 /*注意:本題是讓 b 中達到目標狀態 用到隊列 + 記憶化搜索 2 //代碼一:純模擬---從討論區看見的,由於本題沒有要求輸出的結果是最少的操作次數,所以這種方法也是可以的 3 #include <iostream> 4 5 using namespace std; 6 7 int main() 8 { 9 int ca,cb,n; 10 while (cin >> ca >> cb >> n) 11 { 12 int bnow; 13 int b = 0; 14 while (b != n) 15 { 16 for (int i = 0;i <= (cb - b) / ca;i++) 17 { 18 cout << "fill A" << endl; 19 cout << "pour A B" << endl; 20 bnow = b + ca * (i + 1); 21 if (bnow == n) 22 { 23 break; 24 } 25 } 26 if (bnow == n) 27 { 28 break; 29 } 30 cout << "empty B" << endl; 31 int a; 32 a = ca - (cb - b) % ca; 33 cout << "pour A B" << endl; 34 b = a; 35 if (b == n) 36 { 37 break; 38 } 39 } 40 cout << "success" << endl; 41 } 42 return 0; 43 } 44 */ 45 /* 46 //代碼二: 用STL隊列,可以保證結果肯定是最少的操作次數-----搜索路徑算法還未完成 47 #include <iostream> 48 #include <cstring> 49 //#include <queue> 50 51 using namespace std; 52 53 struct state 54 { 55 int a; 56 int b; 57 int opt; 58 int last_opt; 59 int tot_opt; 60 }; 61 char cmd[6][10] = {"fill A", "fill B", "empty A", "empty B", "pour A B", "pour B A"}; 62 bool visit[1001][1001]; 63 int path[200]; 64 int ca, cb, n; 65 66 67 int BFS(int sa, int sb, int steps) 68 { 69 queue <state> q; 70 front = tail = 0; 71 state t1, t2; 72 t1.a = 0; 73 t1.b = 0; 74 t1.opt = -1; 75 t1.last_opt = -1; 76 t1.tot_opt = 0; 77 q.push(t1); 78 while(!q.empty()) 79 { 80 t2 = q.front(); 81 q.pop(); 82 if(t2.b ==n) 83 { 84 。。。。。。。。 85 。。。。。。。。 86 // 因為用的是stl中的queue,所以這里還沒想到應該咋實現才能回溯遍歷所有的路徑 87 。。。。。。。。 88 } 89 else 90 { 91 state t3; 92 if(t2.a != ca && !visit[ca][t2.b]) //fill A 93 { 94 t3.a = ca; 95 t3.b = t2.b; 96 t3.opt = 0; 97 t3.last_opt = t2.opt; 98 t3.tot_opt = t2.tot_opt + 1; 99 visit[ca][t2.b] = true; 100 q.push(t3); 101 } 102 if(t2.b != cb && !visit[t2.a][cb]) // fill B 103 { 104 t3.a = t2.a; 105 t3.b = cb; 106 t3.opt = 1; 107 t3.last_opt = t2.opt; 108 t3.tot_opt = t2.tot_opt + 1; 109 visit[t2.a][cb] = true; 110 q.push(t3); 111 } 112 if(t2.a != 0 && !visit[0][t2.b]) // empty A 113 { 114 t3.a = 0; 115 t3.b = t2.b; 116 t3.opt = 2; 117 t3.last_opt = t2.opt; 118 t3.tot_opt = t2.tot_opt + 1; 119 visit[0][t2.b] = true; 120 q.push(t3); 121 } 122 if(t2.b != 0 && !visit[t2.a][0]) // empty B 123 { 124 t3.a = t2.a; 125 t3.b = 0; 126 t3.opt = 3; 127 t3.last_opt = t2.opt; 128 t3.tot_opt = t2.tot_opt + 1; 129 visit[t2.a][0] = true; 130 q.push(t3); 131 } 132 if(sb != cb && t2.a != 0) // pour A to B 133 { 134 if(t2.a <= cb - t2.b) 135 { 136 t3.a = 0; 137 t3.b = t2.b + t2.a; 138 } 139 else 140 { 141 t3.a = t2.a - (cb - t2.b); 142 t3.b = cb; 143 } 144 t3.opt = 4; 145 t3.last_opt = t2.opt; 146 t3.tot_opt = t2.tot_opt + 1; 147 visit[t3.a][t3.b] = true; 148 q.push(t3); 149 } 150 if(t2.a != ca && cb != 0) // pour B to A 151 { 152 if(t2.b <= ca - t2.a) 153 { 154 t3.b = 0; 155 t3.a = t2.a + t2.b; 156 } 157 else 158 { 159 t3.a = ca; 160 t3.b = t2.b - (ca - t2.a); 161 } 162 t3.opt = 5; 163 t3.last_opt = t2.opt; 164 t3.tot_opt = t2.tot_opt + 1; 165 visit[t3.a][t3.b] = true; 166 q.push(t3); 167 } 168 } 169 } 170 } 171 172 int main() 173 { 174 while(cin >> ca >> cb >> n) 175 { 176 memset(visit, false, sizeof(visit)); 177 memset(path, 0, sizeof(path)); 178 visit[0][0] = true; 179 int tot_step = BFS(0, 0, 0); 180 for(int i = 1; i <= tot_step; ++i) 181 cout << cmd[path[i]] << endl; 182 cout << "success" <<endl; 183 } 184 return 0; 185 } 186 */ 187 //代碼三:------AC 188 #include <iostream> 189 #include <cstring> 190 191 using namespace std; 192 193 struct state 194 { 195 int a; //記錄當前a中的量 196 int b; //記錄當前b中的量 197 int opt; //記錄當前狀態是由前一狀態怎樣得來的,即記錄的是操作數----對應的是cmd數組的一維下標 198 int last_path; //記錄上一步所在狀態的隊列下標,方便回溯查找路徑 199 int tot_opt; //記錄到底本狀態總共用了多少步 200 }q[10000]; 201 char cmd[6][10] = {"fill A", "fill B", "empty A", "empty B", "pour A B", "pour B A"}; 202 bool visit[1001][1001]; 203 int path[200]; 204 int ca, cb, n; 205 206 207 int BFS(int sa, int sb, int steps) 208 { 209 int front, tail; 210 front = tail = 0; 211 state t1, t2; 212 t1.a = 0; 213 t1.b = 0; 214 t1.opt = -1; 215 t1.last_path = -1; 216 t1.tot_opt = 0; 217 q[tail++] = t1; 218 while(front != tail) 219 { 220 t2 = q[front++]; 221 if(t2.b == n) 222 { 223 state t = t2; 224 for(int i = t.tot_opt; i > 0; --i) 225 { 226 path[i] = t.opt; 227 t = q[t.last_path]; 228 } 229 return t2.tot_opt; 230 } 231 else 232 { 233 state t3; 234 if(t2.a != ca && !visit[ca][t2.b]) //fill A 235 { 236 t3.a = ca; 237 t3.b = t2.b; 238 t3.opt = 0; 239 t3.last_path = front - 1; 240 t3.tot_opt = t2.tot_opt + 1; 241 visit[ca][t2.b] = true; 242 q[tail++] = t3; 243 } 244 if(t2.b != cb && !visit[t2.a][cb]) // fill B 245 { 246 t3.a = t2.a; 247 t3.b = cb; 248 t3.opt = 1; 249 t3.last_path = front - 1; 250 t3.tot_opt = t2.tot_opt + 1; 251 visit[t2.a][cb] = true; 252 q[tail++] = t3; 253 } 254 if(t2.a != 0 && !visit[0][t2.b]) // empty A 255 { 256 t3.a = 0; 257 t3.b = t2.b; 258 t3.opt = 2; 259 t3.last_path = front - 1; 260 t3.tot_opt = t2.tot_opt + 1; 261 visit[0][t2.b] = true; 262 q[tail++] = t3; 263 } 264 if(t2.b != 0 && !visit[t2.a][0]) // empty B 265 { 266 t3.a = t2.a; 267 t3.b = 0; 268 t3.opt = 3; 269 t3.last_path = front - 1; 270 t3.tot_opt = t2.tot_opt + 1; 271 visit[t2.a][0] = true; 272 q[tail++] = t3;; 273 } 274 if(sb != cb && t2.a != 0) // pour A to B 275 { 276 if(t2.a <= cb - t2.b) 277 { 278 t3.a = 0; 279 t3.b = t2.b + t2.a; 280 } 281 else 282 { 283 t3.a = t2.a - (cb - t2.b); 284 t3.b = cb; 285 } 286 t3.opt = 4; 287 t3.last_path = front - 1; 288 t3.tot_opt = t2.tot_opt + 1; 289 visit[t3.a][t3.b] = true; 290 q[tail++] = t3; 291 } 292 if(t2.a != ca && cb != 0) // pour B to A 293 { 294 if(t2.b <= ca - t2.a) 295 { 296 t3.b = 0; 297 t3.a = t2.a + t2.b; 298 } 299 else 300 { 301 t3.a = ca; 302 t3.b = t2.b - (ca - t2.a); 303 } 304 t3.opt = 5; 305 t3.last_path = front - 1; 306 t3.tot_opt = t2.tot_opt + 1; 307 visit[t3.a][t3.b] = true; 308 q[tail++] = t3; 309 } 310 } 311 } 312 } 313 314 int main() 315 { 316 while(cin >> ca >> cb >> n) 317 { 318 memset(visit, false, sizeof(visit)); 319 memset(path, 0, sizeof(path)); 320 visit[0][0] = true; 321 int tot_step = BFS(0, 0, 0); 322 for(int i = 1; i <= tot_step; ++i) 323 cout << cmd[path[i]] << endl; 324 cout << "success" <<endl; 325 } 326 return 0; 327 }