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\n", 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