非常可乐
Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18210Accepted Submission(s): 7388
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
“校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛
问题链接:HDU1495 非常可乐。
题意简述:
平分液体问题。输入s、n和m三个数,分别代表可乐和2个杯子,三个容器可以互相倒,问能不能把s中的可乐平分,能的话输出最小倒杯子的次数,不能就输出NO。
问题分析:
开始的时候,所有可乐在s中,2个杯子n和m都空着。过程中,可以将任何1个容器中的可乐倒到另外某个容器中,或将目标容器倒满,或将源容器倒空。因为容器没有刻度,只能这样。这个过程中,如果出现某个容器空,另外2个容器可乐相同则成功。如果开始的时候,可乐的容量是奇数,则不可能平分可乐。容器间可乐倒来倒去,每次有6种倒法,对这6种倒法进行试探即可。求的是最少倒的次数,所以可以用BFS实现。
程序说明:
搜索过的状态就不需要再搜索了,用数组notvist[][][]来标记搜索过的状态。
AC的C++语言程序如下:
/* HDU1495 非常可乐 */#include <iostream>#include <queue>#include <cstring>#include <cstdio>using namespace std;const int MAXN = 100;int s, n, m, s2;bool notvist[MAXN+1][MAXN+1][MAXN+1];struct node {int s, n, m, level;};int bfs(){if(s % 2 == 1)return -1;queue<node> q;s2 = s / 2;memset(notvist, true, sizeof(notvist));node f;f.s = s;f.n = 0;f.m = 0;f.level=0;q.push(f);notvist[f.s][f.n][f.m] = false;while(!q.empty()) {f = q.front();q.pop();if((f.s == f.n && f.s == s2) || (f.s == f.m && f.s == s2) || (f.m == f.n && f.m == s2))return f.level;node v;// s --> nif(f.s && n - f.n > 0) {if(f.s > n - f.n) { // s > n的剩余容量v.s = f.s - (n - f.n);v.n = n;v.m = f.m;} else {// s <= n的剩余容量v.s = 0;v.n = f.n + f.s;v.m = f.m;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}// s --> mif(f.s && m - f.m > 0) {if(f.s > m - f.m) { // s > m的剩余容量v.s = f.s - (m - f.m);v.n = f.n;v.m = m;} else {// s <= m的剩余容量v.s = 0;v.n = f.n;v.m = f.m + f.s;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}// n --> sif(f.n && s - f.s > 0) {if(f.n > s - f.s) { // n > s的剩余容量v.s = s;v.n = f.n - (s - f.s);v.m = f.m;} else {// n <= s的剩余容量v.s = f.s + f.n;v.n = 0;v.m = f.m;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}// n --> mif(f.n && m - f.m > 0) {if(f.n > m - f.m) { // n > m的剩余容量v.s = f.s;v.n = f.n - (m - f.m);v.m = m;} else {// n <= m的剩余容量v.s = f.s;v.n = 0;v.m = f.m + f.n;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}// m --> sif(f.m && s - f.s > 0) {if(f.m > s - f.s) { // m > s的剩余容量v.s = s;v.n = f.n;v.m = f.m - (s - f.s);} else {// m <= s的剩余容量v.s = f.s + f.m;v.n = f.n;v.m = 0;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}// m --> nif(f.m && n - f.n > 0) {if(f.m > n - f.n) { // m > n的剩余容量v.s = f.s;v.n = n;v.m = f.m - (n - f.n);} else {// m <= n的剩余容量v.s = f.s;v.n = f.n + f.m;v.m = 0;}if(notvist[v.s][v.n][v.m]) {notvist[v.s][v.n][v.m] = false;v.level = f.level + 1;q.push(v);}}}return -1;}int main(){while(scanf("%d%d%d", &s, &n, &m) != EOF) {if(s == 0 && n == 0 && m == 0)break;int ans = bfs();if(ans < 0)printf("NO\n");elseprintf("%d\n", ans);}return 0;}