小记:这题给我留下了一个TLE的印记,之前因为用的标记数组是int型的,导致了一直TLE,唉,memset一个int型数组浪费的时间真多,不然我之前的那个没用结构体的直接bfs的应该可以A过去,唉,又,b了。一般在写代码前都会先分析自己的算法的时间复杂度的大小,而觉得可以的,动手写了之后还是超时,要么就是你的想法错了,要么就是你的优化剪枝不够,而对于常数级优化 则是没必要的。谨记。。。
题解:题目要求 n + m == s 那么每一次的倒可乐就可以从这一杯倒到另外两杯去,而有三个杯子因此有6种倒的方法。即相当于一颗六叉树。bfs 搜索每一种状态,当有两个杯子是s的一半的时候,那个状态就是答案,输出即可。已搜过的进行标记。
剪枝:若s 为奇数,则无解,分不了相等的两半,因为你不能倒出一个0.5的状态值。
优化:标记数组设为bool型。我的设int型,156MS,设bool型,31MS。
代码奉上:
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define MAX 101 struct NODE { int x,y,z,t; }; bool visited[MAX][MAX][MAX]; void bfs(int s,int n,int m) { queue<NODE>q; NODE now, next; now.x = s; now.y = 0; now.z = 0; now.t = 0; q.push(now); memset(visited,0,sizeof(visited)); while(!q.empty()) { now = q.front(); q.pop(); if((now.x == s>>1 && now.y == s>>1) || (now.x == s>>1 && now.z == s>>1) || (now.z == s>>1 && now.y == s>>1)){ printf("%d\n",now.t); return ; } if(now.x) { if(now.x > (n - now.y)){ next.x = now.x - n + now.y; next.y = n; next.z = now.z; } else { next.x = 0; next.y = now.y + now.x; next.z = now.z; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } if(now.x > (m - now.z)){ next.x = now.x - m + now.z; next.z = m; next.y = now.y; } else { next.x = 0; next.z = now.z+ now.x; next.y = now.y; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } if(now.y) { if(now.y > (s - now.x)){ next.y = now.y - s + now.x; next.x = s; next.z = now.z; } else { next.y = 0; next.x = now.y+ now.x; next.z = now.z; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } if(now.y > (m - now.z)){ next.y = now.y - m + now.z; next.z = m; next.x = now.x; } else { next.y = 0; next.z = now.z+ now.y; next.x = now.x; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } if(now.z) { if(now.z > (s - now.x)){ next.z = now.z - s + now.x; next.x = s; next.y = now.y; } else { next.z = 0; next.x = now.z+ now.x; next.y = now.y; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } if(now.z > (n - now.y)){ next.z = now.z - n + now.y; next.y = n; next.x = now.x; } else { next.z = 0; next.y = now.z+ now.y; next.x = now.x; } if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } } puts("NO"); return ; } int main() { int s, n, m; while(scanf("%d%d%d",&s,&n,&m),s||n||m) { if(s%2){ puts("NO"); } else { bfs(s,n,m); } } return 0; }
简化一点点:
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define MAX 101 typedef struct n { int x,y,z,t; }NODE; bool visited[MAX][MAX][MAX]; int s, n, m; int judge(NODE p){ if((p.x == p.y && p.x + p.y == s) || (p.x == p.z && p.x + p.z == s) || (p.z == p.y && p.z + p.y == s)){ return 1; } return 0; } void bfs() { queue<NODE>q; NODE now,next; now.x = s; now.y = 0; now.z = 0; now.t = 0; q.push(now); memset(visited,0,sizeof(visited)); while(!q.empty()) { now = q.front(); q.pop(); if(judge(now)){ printf("%d\n",now.t); return ; } if(now.x) { next.x = (now.x > (n - now.y))? now.x - n + now.y: 0; next.y = (now.x > (n - now.y))? n: now.y + now.x; next.z = now.z; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } next.x = (now.x > (m - now.z))? now.x - m + now.z: 0; next.z = (now.x > (m - now.z))? m: now.z + now.x; next.y = now.y; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } if(now.y) { next.y = (now.y > (s - now.x))? now.y - s + now.x: 0; next.x = (now.y > (s - now.x))? s: now.x + now.y; next.z = now.z; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } next.y = (now.y > (m - now.z))? now.y - m + now.z: 0; next.z = (now.y > (m - now.z))? m: now.z + now.y; next.x = now.x; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } if(now.z) { next.z = (now.z > (s - now.x))? now.z - s + now.x: 0; next.x = (now.z > (s - now.x))? s: now.z + now.x; next.y = now.y; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } next.z = (now.z > (n - now.y))? now.z - n + now.y: 0; next.y = (now.z > (n - now.y))? n: now.z + now.y; next.x = now.x; if(!visited[next.x][next.y][next.z]) { visited[next.x][next.y][next.z] = 1; next.t = now.t + 1; q.push(next); } } } puts("NO"); return ; } int main() { while(scanf("%d%d%d",&s,&n,&m),s||n||m) { if(s%2){ puts("NO"); } else { bfs(); } } return 0; }