标签:open break clu next alt 原来 ring namespace print
这道题TLE了很多次,原来一直以为将数字化为最简可以让运算更快,但是去了简化之后才发现,真正耗时的就是化简....还和队友学到了用状态少直接数组模拟刚就能过...
本题大意:给出可乐的体积v1,给出两个杯子v2和v3,要求v2 + v3 == v1,每次只能从一个杯子倒到另一个杯子,问最少倒多少次可以将可乐平分。
思路:最后可乐肯定在可乐瓶和大杯子里面,直接DFS搜就行了。
参考代码:
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 6 struct node { 7 int cur[3], step; 8 } now, Next; 9 10 const int maxn = 100 + 5; 11 int v[3]; 12 int ans, t; 13 bool flag; 14 bool vis[maxn][maxn][maxn]; 15 16 void bfs() { 17 if(v[0] & 1) { 18 flag = false; 19 return; 20 } 21 queue <node> Q; 22 now.cur[0] = v[0], now.cur[1] = 0, now.cur[2] = 0, now.step = 0; 23 vis[v[0]][0][0] = true; 24 Q.push(now); 25 while(!Q.empty()) { 26 now = Q.front(); 27 Q.pop(); 28 if(now.cur[0] == now.cur[1] && now.cur[2] == 0) { 29 ans = now.step; 30 return; 31 } 32 for(int i = 0; i < 3; i ++) {//i -> j 33 for(int j = 0; j < 3; j ++) { 34 if(i != j) { 35 Next = now; 36 t = now.cur[i] + now.cur[j]; 37 if(t > v[j]) Next.cur[j] = v[j]; 38 else Next.cur[j] = t; 39 Next.cur[i] = t - Next.cur[j]; 40 if(!vis[Next.cur[0]][Next.cur[1]][Next.cur[2]]) { 41 Next.step = now.step + 1; 42 Q.push(Next); 43 vis[Next.cur[0]][Next.cur[1]][Next.cur[2]] = true; 44 } 45 } 46 } 47 } 48 } 49 flag = false; 50 } 51 52 int main () { 53 while(~scanf("%d %d %d", &v[0], &v[1], &v[2])) { 54 memset(vis, false, sizeof(vis)); 55 if(v[0] == 0 && v[1] == 0 && now.cur[2] == 0) break; 56 flag = true, ans = 0; 57 if(v[1] < v[2]) { 58 t = v[1]; 59 v[1] = v[2]; 60 v[2] = t; 61 } 62 bfs(); 63 if(flag) printf("%d\n", ans); 64 else printf("NO\n"); 65 } 66 return 0; 67 }
下面这个代码的效率要高一点,区别在于倒水方式不同。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 6 struct node { 7 int cur[3], step; 8 } now, Next; 9 10 const int maxn = 100 + 5; 11 int v[3]; 12 int ans, t; 13 bool flag; 14 bool vis[maxn][maxn][maxn]; 15 16 void bfs() { 17 if(v[0] & 1) { 18 flag = false; 19 return; 20 } 21 queue <node> Q; 22 now.cur[0] = v[0], now.cur[1] = 0, now.cur[2] = 0, now.step = 0; 23 vis[v[0]][0][0] = true; 24 Q.push(now); 25 while(!Q.empty()) { 26 now = Q.front(); 27 Q.pop(); 28 if(now.cur[0] == now.cur[1] && now.cur[2] == 0) { 29 ans = now.step; 30 return; 31 } 32 for(int i = 0; i < 3; i ++) {//i -> j 33 for(int j = 0; j < 3; j ++) { 34 if(i != j) { 35 Next = now; 36 if(j == 0) { 37 Next.cur[j] = now.cur[j] + now.cur[i]; 38 Next.cur[i] = 0; 39 } else if(j == 1) { 40 t = v[1] - now.cur[j]; 41 Next.cur[i] = now.cur[i] - t; 42 Next.cur[i] = Next.cur[i] > 0 ? Next.cur[i] : 0; 43 Next.cur[j] = now.cur[j] + now.cur[i]; 44 Next.cur[j] = Next.cur[j] < v[1] ? Next.cur[j] : v[1]; 45 } else { 46 t = v[2] - now.cur[j]; 47 Next.cur[i] = now.cur[i] - t; 48 Next.cur[i] = Next.cur[i] > 0 ? Next.cur[i] : 0; 49 Next.cur[j] = now.cur[j] + now.cur[i]; 50 Next.cur[j] = Next.cur[j] < v[2] ? Next.cur[j] : v[2]; 51 } 52 if(!vis[Next.cur[0]][Next.cur[1]][Next.cur[2]]) { 53 Next.step = now.step + 1; 54 Q.push(Next); 55 vis[Next.cur[0]][Next.cur[1]][Next.cur[2]] = true; 56 } 57 } 58 } 59 } 60 } 61 flag = false; 62 } 63 64 int main () { 65 while(~scanf("%d %d %d", &v[0], &v[1], &v[2])) { 66 memset(vis, false, sizeof(vis)); 67 if(v[0] == 0 && v[1] == 0 && now.cur[2] == 0) break; 68 flag = true, ans = 0; 69 if(v[1] < v[2]) { 70 t = v[1]; 71 v[1] = v[2]; 72 v[2] = t; 73 } 74 bfs(); 75 if(flag) printf("%d\n", ans); 76 else printf("NO\n"); 77 } 78 return 0; 79 }
标签:open break clu next alt 原来 ring namespace print
原文地址:https://www.cnblogs.com/bianjunting/p/10493581.html