非常可乐
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 27010 Accepted Submission(s): 10487
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
总结经验:以后可以把所有情况枚举出来的就用bfs。
这道题互相倒来倒去总共有6种情况,比如说三个容器名就叫s,n,m:
- s -> n
- s -> m
- n -> s
- n -> m
- m -> s
- m -> n
然后就把所有情况用if枚举出来的咯,比如说要看是不是第一种情况,那判断的条件就是s里面有可乐,n还没倒满,其中还要分两种情况,1.s足够把n倒满。2.s还不能够把n倒满。 以此类推其他5种情况。
判断的条件是两个容器里面的可乐相等,并且这两个容器里的可乐加起来就为总的可乐容量(s)。
若队列空了,还没有返回步数,那就说明平分不了,返回-1,所以是在while循环外面写上return -1;
下面附上ac代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <queue>
#include <cmath>
#define INF 0x3f3f3f3f
#define mod 1000000007
using namespace std;
typedef long long int ll;
int s,n,m;
int sgn[105][105][105];
struct node {
int s,n,m,step;
};
bool check(int s,int n,int m) { //判断是否已经“走过”这种状态
if(sgn[s][n][m] == 1) {
return false;
}
return true;
}
bool succeed(int ss,int nn,int mm) { //判断是否已经平分
if(ss == nn && ss + nn == s) { //****这里不能写mm == 0 !
return true; //7 4 3 -> 7 0 0 ->4 4 3 DENIED
} else if(ss == mm && ss + mm == s) {
return true;
} else if(nn == mm && nn + mm == s) {
return true;
} else {
return false;
}
}
int bfs() {
memset(sgn,0,sizeof(sgn)); //初始化为0
node cur,next;
cur.s = s;
cur.n = 0; //** 注意:一开始n和m两个杯子还没有可乐
cur.m = 0; //**
sgn[s][0][0] = 1; //标记这种情况已经"走过"了 是s 0 0 !不是s n m!
cur.step = 0;
queue<node>q;
q.push(cur);
while(!q.empty()) {
cur = q.front();
q.pop();
if(succeed(cur.s,cur.n,cur.m)) {
return cur.step;
}
if(cur.s > 0 && cur.n < n) { //互相倒一共有6种情况 //1
if(cur.s > n - cur.n) {
next.s = cur.s - (n - cur.n);
next.n = n;
next.m = cur.m; //是cur.m! 不是m!
} else {
next.s = 0;
next.n = cur.n + cur.s;
next.m = cur.m;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
if(cur.s > 0 && cur.m < m) { // 2
if(cur.s > m - cur.m) {
next.s = cur.s - (m - cur.m);
next.n = cur.n;
next.m = m;
} else {
next.s = 0;
next.n = cur.n;
next.m = cur.m + cur.s;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
if(cur.n > 0 && cur.s < s) { // 3
if(cur.n > s - cur.s) {
next.s = s;
next.n = cur.n - (s - cur.s);
next.m = cur.m;
} else {
next.s = cur.s + cur.n;
next.n = 0;
next.m = cur.m;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
if(cur.n > 0 && cur.m < m) { // 4
if(cur.n > m - cur.m) {
next.s = cur.s;
next.n = cur.n - (m - cur.m);
next.m = m;
} else {
next.s = cur.s;
next.n = 0;
next.m = cur.m + cur.n;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
if(cur.m > 0 && cur.s < s) { // 5
if(cur.m > s - cur.s) {
next.s = s;
next.n = cur.n;
next.m = cur.m - (s - cur.s);
} else {
next.s = cur.s + cur.m;
next.n = cur.n;
next.m = 0;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
if(cur.m > 0 && cur.n < n) { // 6
if(cur.m > n - cur.n) {
next.s = cur.s;
next.n = n;
next.m = cur.m - (n - cur.n);
} else {
next.s = cur.s;
next.n = cur.n + cur.m;
next.m = 0;
}
if(check(next.s,next.n,next.m)) {
sgn[next.s][next.n][next.m] = 1;
next.step = cur.step + 1;
q.push(next);
}
}
}
return -1;
}
int main() {
while(cin >> s >> n >> m) {
if(s == 0 && n == 0 && m == 0) {
break;
}
if(bfs() == -1) {cout << "NO" << endl;}
else {cout << bfs() << endl;}
}
return 0;
}