HDU 1495 非常可乐

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1495

题目大意:给你三个瓶子,第一个瓶子容量S,装满了S单位的可乐。另外两个瓶子容量等于第一个。三个瓶子都无刻度。给出三个瓶子容量,问能否将第一个瓶子装S/2的可乐,其余两个瓶子无所谓,中途不能喝可乐。

解题思路:单纯看来像是个数学题(好像确实能用数学做),但是可以认为,三个瓶子初始状态(s,0,0),终止状态(s/2, x, x),那么宽搜即可。

搜索过程实际就是状态转移的过程。每次可以有S->M, S->N, M->S, M->N, N->S, N->M六个状态,但细节稍微复杂,仔细考虑也不算麻烦。

代码:

  1 const int maxn = 105;
  2 int s, m, n;
  3 struct node{
  4     int s, n, m;
  5     int t;
  6 };
  7 int vis[maxn][maxn];
  8 queue<node> q; 
  9 
 10 int bfs(){
 11     memset(vis, 0, sizeof(vis));
 12     while(!q.empty()) q.pop();
 13     node u;
 14     u.s = s; u.m = u.n = u.t = 0;
 15     vis[s][0] = 1;
 16     q.push(u);
 17     bool flag = false;
 18     while(!q.empty()){
 19         u = q.front(); q.pop();
 20         if(u.s == s / 2) {
 21             flag = true;
 22             break;
 23         }
 24         u.t++;
 25         if(u.n < n) {
 26             node v = u;
 27             if(v.s <= (n - v.n)){
 28                 v.n += v.s; v.s = 0; 
 29             }
 30             else{    
 31                 v.s -= (n - v.n);
 32                 v.n = n; 
 33             }
 34             if(!vis[v.s][v.n]){    
 35                 q.push(v);
 36                 vis[v.s][v.n] = 1;
 37             }
 38             
 39             v = u;
 40             if(v.m <= (n - v.n)){
 41                 v.n += v.m; v.m = 0; 
 42             }
 43             else{
 44                 v.m -= (n - v.n); v.n = n;
 45             }
 46             if(!vis[s - v.m - v.n][v.n]){ 
 47                 q.push(v);
 48                 vis[s - v.m - v.n][v.n] = 1;
 49             }
 50         }
 51         if(u.m < m){
 52             node v = u;
 53             if(v.s <= (m - v.m)){
 54                 v.m += v.s; v.s = 0; 
 55             }
 56             else{
 57                 v.s -= (m - v.m); v.m = m;
 58             }
 59             if(!vis[v.s][s - v.s - v.m]){
 60                 q.push(v);
 61                 vis[v.s][s - v.s - v.m] = 1;
 62             }
 63             
 64             v = u;
 65             if(v.n <= (m - v.m)){
 66                 v.m += v.n; v.n = 0; 
 67             }
 68             else{
 69                 v.n -= (m - v.m); v.m = m;
 70             }
 71             if(!vis[s - v.n - v.m][v.n]){
 72                 q.push(v);
 73                 vis[s - v.n - v.m][v.n] = 1;
 74             }
 75         }
 76         if(u.s < s){
 77             node v = u;
 78             if(v.m <= s - v.s){
 79                 v.s += v.m; v.m = 0; 
 80             }
 81             else{
 82                 v.m -= (s - v.s); v.s = s;
 83             }
 84             if(!vis[v.s][s - v.m - v.s]){
 85                 q.push(v);
 86                 vis[v.s][s - v.m - v.s] = 1;
 87             }
 88             
 89             v = u;
 90             if(v.n <= s - v.s){
 91                 v.s += v.n; v.n = 0;
 92             }
 93             else{
 94                 v.n -= s - v.s; v.s = s;
 95             }
 96             if(!vis[v.s][v.n]){
 97                 q.push(v);
 98                 vis[v.s][v.n] = 1;
 99             }
100         }
101     }
102     if(!flag) return -1;
103     return u.t;
104 }
105 
106 int main(){
107     while(scanf("%d %d %d", &s, &n, &m) != EOF && s != 0){
108         if(s & 1) {
109             puts("NO");
110             continue;
111         }
112         else if(n == m){
113             puts("1");
114             continue;
115         }
116         else{
117             int ans = bfs();
118             if(ans == -1) puts("NO");
119             else printf("%d
", ans);
120         }
121     }
122 }

题目:

非常可乐

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16616    Accepted Submission(s): 6709


Problem Description
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
 

 

Input
三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。
 

 

Output
如果能平分的话请输出最少要倒的次数,否则输出"NO"。
 

 

Sample Input
7 4 3 4 1 3 0 0 0
 

 

Sample Output
NO 3
 

 

Author
seeyou
 

 

Source
 
原文地址:https://www.cnblogs.com/bolderic/p/7342928.html