HDU1495:非常可乐
题目描述
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是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求最优解
代码如下
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <list>
#include<sstream>
#include<ctime>
using namespace std;
int S,N,M,flag;
struct node //当前三个容器中的量,和到该状态所用操作次数
{
int s;
int n;
int m;
int step;
};
queue<node> que;
int f[105][105][105];
int panduan(int a,int b,int c) // 判断是否平分
{ // 如果三个容器中有两个的量相等且第个容器中的量为0说明已经平分
if(a==b&&c==0) return 1;
if(a==c&&b==0) return 1;
if(b==c&&a==0) return 1;
return 0;
}
void bfs()
{
while(!que.empty())
{
node u=que.front();
que.pop();
if(panduan(u.s,u.n,u.m)) // 如果已经平分,则输出结果,结束
{
flag=1;
cout<<u.step<<endl;
return;
}
node v; //有6种不同操作
if(u.s!=0&&u.n!=N) // 1.s倒给n
{
if(u.s+u.n<=N)
{
v.s=0;
v.n=u.s+u.n;
v.m=u.m;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.s+u.n>N)
{
v.s=u.s+u.n-N;
v.n=N;
v.m=u.m;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
if(u.n!=0&&u.s!=S) //2.n倒给s
{
if(u.s+u.n<=S)
{
v.s=u.s+u.n;
v.n=0;
v.m=u.m;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.s+u.n>S)
{
v.s=S;
v.n=u.s+u.n-S;
v.m=u.m;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
if(u.s!=0&&u.m!=M) //3.s倒给m
{
if(u.s+u.m<=M)
{
v.s=0;
v.m=u.s+u.m;
v.n=u.n;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.s+u.m>M)
{
v.s=u.s+u.m-M;
v.m=M;
v.n=u.n;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
if(u.m!=0&&u.s!=S) //4.m倒给s
{
if(u.s+u.m<=S)
{
v.m=0;
v.s=u.s+u.m;
v.n=u.n;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.s+u.m>S)
{
v.m=u.s+u.m-S;
v.s=S;
v.n=u.n;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
if(u.n!=0&&u.m!=M) //5.把n倒给m
{
if(u.n+u.m<=M)
{
v.m=u.m+u.n;
v.n=0;
v.s=u.s;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.n+u.m>M)
{
v.m=M;
v.n=u.n+u.m-M;
v.s=u.s;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
if(u.m!=0&&u.n!=N) // 6.把m倒给n
{
if(u.m+u.n<=N)
{
v.m=0;
v.n=u.n+u.m;
v.s=u.s;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
else if(u.m+u.n>N)
{
v.n=N;
v.m=u.m+u.n-N;
v.s=u.s;
v.step=u.step+1;
if(f[v.s][v.n][v.m]==0)
{
que.push(v);
f[v.s][v.n][v.m]=1;
}
}
}
}
}
int main()
{
while(cin>>S>>N>>M)
{
flag=0;
if(!(S+N+M))
break;
if(S%2!=0) //如果初始量不能被2整除,则不可能被平分
cout<<"NO\n";
else
{
memset(f,0,sizeof(f)); //初始化
while(!que.empty())
que.pop();
node u;
u.s=S;
u.m=0;
u.n=0;
u.step=0;
que.push(u); //将初始状态入队
bfs();
if(flag==0) //如果无解
cout<<"NO\n";
}
}
return 0;
}