Title Link: https://vjudge.net/problem/HDU-1495
There are two empty cups (N l and M L respectively) and A full can of coke (S l), S = N + M, three containers can be poured into each other. If A is poured into B, there are only two cases:
(1) pour all A into B, and the number of liters in B is less than or equal to the maximum capacity of B.
(2) part A is poured into Part B, and B has reached the maximum capacity of B.
Question: is it possible to divide the S-liter coke equally into any two containers? If so, the minimum number of operations can be obtained. Otherwise, the output "NO".
Idea: bfs, which simulates enumeration in all six cases (code writing is more vivid), needs to mark the capacity of the three containers, otherwise it will TLE.
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 //It's embedded if Indicates (1) situation 32 // else Indicates (2) situation 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 //As you can see, I used two methods to mark the situation. 76 void bfs(){ 77 78 map<pair<int, int>, bool> mp;//Mark the capacity of three containers to prevent them from appearing in the queue again. 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 //Six cases, Pour(x,y) hold X Pour in y It should be very clear 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 //Check if there is a split 103 int key = 0; 104 if (t.N == AVE) key++; 105 if (t.M == AVE) key++; 106 if (t.S == AVE) key++; 107 //Bisection 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 }