題意:有兩個空杯(分別是N升和M升)和一罐滿的可樂S升,S = N + M,三個容器能夠互相傾倒,若是A倒入B,只有兩種狀況:
(1) A所有倒入B中,B中的升數小於等於B的最大容量。
(2)A部分倒入B中,B已經到達了B的最大容量。
問:有沒有可能把S升的可樂平分在任意兩個容器中,有的話得出最少操做次數,不然輸出「NO」。node
思路:bfs,把六種狀況都模擬枚舉(代碼寫的比較形象),須要標記出現過的三個容器的容量狀況,不然會TLE。ios
1 #include <iostream> 2 #include <cstring> 3 #include<vector> 4 #include<string> 5 #include <cmath> 6 #include <map> 7 #include <queue> 8 #include <algorithm> 9 using namespace std; 10 11 #define inf (1LL << 31) - 1 12 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 13 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 14 #define per(i,j,k) for(int i = (j); i >= (k); i--) 15 #define per__(i,j,k) for(int i = (j); i > (k); i--) 16 17 int NL, ML, SL, AVE; 18 //bool vis[110][110][110]; 19 20 struct node{ 21 22 int N, M, S, V; 23 24 node(int a, int b, int c, int d){ 25 N = a; 26 M = b; 27 S = c; 28 V = d; 29 } 30 31 //這裏面內嵌的 if表示(1)狀況 32 // else表示(2)狀況 33 void Pour(int f, int s){ 34 35 if (f == 1){ 36 if (s == 2){ 37 int t = ML - M; 38 if (N >= t) N -= t, M = ML; //(1) 39 else M += N, N = 0; //(2) 40 } 41 else if (s == 3){ 42 int t = SL - S; 43 if (N >= t) N -= t, S = SL; 44 else S += N, N = 0; 45 } 46 } 47 else if (f == 2){ 48 if (s == 1){ 49 int t = NL - N; 50 if (M >= t) M -= t, N = NL; 51 else N += M, M = 0; 52 } 53 else if (s == 3){ 54 int t = SL - S; 55 if (M >= t) M -= t, S = SL; 56 else S += M, M = 0; 57 } 58 } 59 else if (f == 3){ 60 if (s == 1){ 61 int t = NL - N; 62 if (S >= t) S -= t, N = NL; 63 else N += S, M = 0; 64 } 65 else if (s == 2){ 66 int t = ML - M; 67 if (S >= t) S -= t, M = ML; 68 else M += S, S = 0; 69 } 70 } 71 } 72 73 }; 74 75 //能夠看出,我用了兩個方法均可以標記狀況 76 void bfs(){ 77 78 map<pair<int, int>, bool> mp;//標記三個容器的容量狀況,防止出下過的再次出如今隊列中 79 pair<int, int > p(0, 0); 80 mp[p] = true; 81 node in(0, 0, SL, 0); 82 // vis[in.N][in.M][in.S] = true; 83 queue<node> que; 84 que.push(in); 85 86 while (!que.empty()){ 87 88 node tmp = que.front(); 89 que.pop(); 90 91 //六種狀況,Pour(x,y) 把X中的倒入y中,應該是很清楚了 92 rep(i, 1, 6){ 93 node t = tmp; 94 95 if (i == 1) t.Pour(1, 2); 96 else if (i == 2) t.Pour(1, 3); 97 else if (i == 3) t.Pour(2, 1); 98 else if (i == 4) t.Pour(2, 3); 99 else if (i == 5) t.Pour(3, 1); 100 else if (i == 6) t.Pour(3, 2); 101 102 //檢查有沒有出現平分了 103 int key = 0; 104 if (t.N == AVE) key++; 105 if (t.M == AVE) key++; 106 if (t.S == AVE) key++; 107 //平分了 108 if (key >= 2){ 109 cout << tmp.V + 1 << endl; 110 return; 111 } 112 113 p.first = t.N; 114 p.second = t.M; 115 pair<int, int > p(t.N, t.M); 116 if (!mp[p]/*!vis[t.N][t.M][t.S]*/){ 117 mp[p] = true; 118 // vis[t.N][t.M][t.S] = true; 119 que.push(node{ t.N, t.M, t.S, tmp.V + 1 }); 120 } 121 } 122 } 123 124 cout << "NO" << endl; 125 } 126 127 int main(){ 128 129 ios::sync_with_stdio(false); 130 cin.tie(0); 131 132 while (cin >> SL >> NL >> ML){ 133 134 memset(vis, 0, sizeof(vis)); 135 136 if (NL == 0 && ML == 0 && SL == 0) break; 137 AVE = SL / 2; 138 if (SL & 1){ 139 cout << "NO" << endl; 140 continue; 141 } 142 bfs(); 143 } 144 145 return 0; 146 }