非常可樂
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;
}