POJ_3414 Pots 【複雜BFS】
一、題面
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- POUR(i,j) pour from pot i
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
Input
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
Output
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible
Sample Input
3 5 4
Sample Output
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
二、分析
對於這題,難點不在BFS的思路,難點在於BFS每一次父節點生成孩子結點的時候,情況比較複雜。對於記錄路徑,仍然需要使用孩子節點標記一個字首指向父節點,然後用遞迴的方式實現即可。自己在寫程式碼的時候非常不注意,在生成孩子節點時,對於標記訪問的陣列,本來應該用=,但我直接複製的判斷條件裡的==,導致一直RE。謹記!
三、AC程式碼
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 const int MAXN = 100; 7 bool visit[MAXN+3][MAXN+3]; 8 int A, B, C; 9 10 struct Point 11 { 12 int first, second, cnt; 13 int prev, id; //父節點和操作物件 14 char op; //操作 15 }; 16 17 Point P[MAXN*MAXN + 4]; 18 int Cnt, Ans; 19 20 void Output(int t) 21 { 22 if(P[t].prev != -1) 23 { 24 Ans++; 25 Output(P[t].prev); 26 } 27 if(Ans != -1) 28 { 29 printf("%d\n", Ans); 30 Ans = -1; 31 } 32 if(P[t].op=='F') 33 { 34 printf("FILL(%d)\n", P[t].id); 35 } 36 else if(P[t].op == 'P') 37 { 38 printf("POUR(%d,%d)\n", P[t].id, P[t].id==1?2:1); 39 } 40 else if(P[t].op == 'D') 41 { 42 printf("DROP(%d)\n", P[t].id); 43 } 44 } 45 46 void BFS() 47 { 48 Point t; 49 int cur; 50 t.first = 0, t.second = 0; 51 visit[0][0] = 1; 52 t.op = '0', t.prev = -1, t.id = -1; 53 t.cnt = 0; 54 P[0] = t; 55 Cnt = 1; 56 cur = 0; 57 58 while(true) 59 { 60 if(cur >= Cnt) 61 { 62 printf("impossible\n"); 63 return; 64 } 65 Point pt = P[cur++]; 66 67 if(pt.first == C || pt.second == C) 68 { 69 Ans = 0; 70 Output(pt.cnt); 71 break; 72 } 73 74 t.prev = pt.cnt; 75 76 if(pt.first < A) 77 { 78 t.first = A; 79 t.second = pt.second; 80 if(visit[t.first][t.second] == 0) 81 { 82 //visit[t.first][t.second] == 1; 剛開始RE的原因 83 visit[t.first][t.second] = 1; 84 t.op = 'F'; 85 t.id = 1; 86 t.cnt = Cnt; 87 P[Cnt++] = t; 88 89 } 90 } 91 92 if(pt.second < B) 93 { 94 t.first = pt.first; 95 t.second = B; 96 if(visit[t.first][t.second] == 0) 97 { 98 visit[t.first][t.second] = 1; 99 t.op = 'F'; 100 t.id = 2; 101 t.cnt = Cnt; 102 P[Cnt++] = t; 103 } 104 } 105 106 if(pt.first < A && pt.second > 0 ) 107 { 108 t.first = pt.first + pt.second; 109 t.second = t.first - A; 110 if(t.second < 0) 111 t.second = 0; 112 else 113 t.first = A; 114 if(visit[t.first][t.second] == 0) 115 { 116 visit[t.first][t.second] = 1; 117 t.op = 'P'; 118 t.id = 2; 119 t.cnt = Cnt; 120 P[Cnt++] = t; 121 } 122 } 123 124 if(pt.second < B && pt.first > 0) 125 { 126 t.second = pt.second + pt.first; 127 t.first = t.second - B; 128 if(t.first < 0) 129 t.first = 0; 130 else 131 t.second = B; 132 if(visit[t.first][t.second] == 0) 133 { 134 visit[t.first][t.second] = 1; 135 t.op = 'P'; 136 t.id = 1; 137 t.cnt = Cnt; 138 P[Cnt++] = t; 139 } 140 } 141 142 if(pt.first > 0) 143 { 144 t.first = 0; 145 t.second = pt.second; 146 if(visit[t.first][t.second] == 0) 147 { 148 visit[t.first][t.second] = 1; 149 t.op = 'D'; 150 t.id = 1; 151 t.cnt = Cnt; 152 P[Cnt++] = t; 153 } 154 } 155 156 if(pt.second > 0) 157 { 158 t.first = pt.first; 159 t.second = 0; 160 if(visit[t.first][t.second] == 0) 161 { 162 visit[t.first][t.second] = 1; 163 t.op = 'D'; 164 t.id = 2; 165 t.cnt = Cnt; 166 P[Cnt++] = t; 167 } 168 } 169 } 170 } 171 172 int main() 173 { 174 while(scanf("%d %d %d", &A, &B, &C)!=EOF) 175 { 176 memset(visit, 0, sizeof(visit)); 177 BFS(); 178 } 179 return 0; 180 }View Code