题目链接:非常可乐
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是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 种可以相互顷倒情况( a->b a->s b->a b->s s->a s->b)
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct Node{
int a;
int b;
int s;
int t;//记录步数
}e[105],st;
int a,b,s;
int vis[105][105];
int bfs()
{
queue<Node>q;
memset(vis,0,sizeof(vis));
st.a = 0;
st.b = 0;
st.t = 0;
st.s = s;
q.push(st);
vis[a][b] = 1;
while(!q.empty())
{
Node u = q.front(),v;// 用 u 表示当前,用 v 表示下一次 a b s 体积
q.pop();
if(u.a== s/2 && u.s == s/2)// a 和 s 中可乐体积 都是原容量的一半
{
return u.t;
}
if(u.s && u.a != a)//s -> a
{
int c = a - u.a;
if(u.s >= c)
{
v.a =a;
v.s = u.s - c;
}
else {
v.a = u.a + u.s;
v.s = 0;
}
v.b = u.b;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v.b] = 1;
}
}
if(u.s && u.b != b) // s -> b
{
int c = b - u.b;
if(u.s >= c)
{
v.s = u.s - c;
v.b = b;
}
else {
v.b = u.b + u.s;
v.s = 0;
}
v.a = u.a;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v.b] = 1;
}
}
if(u.a && u.s != s)// a -> s
{
int c = s - u.s;
if(u.a >= c)
{
v.s = s;
v.a = u.a - c;
}
else {
v.s = u.s + u.a;
v.a = 0;
}
v.b = u.b;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v,b] = 1;
}
}
if(u.a && u.b != b) // a -> b
{
int c = b - u.b;
if(u.a >= c)
{
v.b = b;
v.a = u.a - c;
}
else {
v.b = u.b + u.a;
v.a = 0;
}
v.s = u.s;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v.b] = 1;
}
}
if(u.b && u.a != a)// b -> a
{
int c = a - u.a;
if(u.b >= c)
{
v.a = a;
v.b = u.b - c;
}
else {
v.a = u.a + u.b;
v.b = 0;
}
v.s = u.s;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v.b] = 1;
}
}
if(u.b && u.s != s)//b->s
{
int c = s - u.s;
if(u.b >= c)
{
v.s = s;
v.b = u.b - c;
}
else {
v.s = u.s + u.b;
v.b = 0;
}
v.a = u.a;
v.t = u.t + 1;
if(!vis[v.a][v.b])
{
q.push(v);
vis[v.a][v.b] = 1;
}
}
}
return 0;
}
int main()
{
while(scanf("%d%d%d",&s,&a,&b),s||a||b)
{
if(s%2)
{
cout<<"NO"<<endl; // 如果是奇数 ,肯定不满足条件
continue;
}
if(a<b) swap(a,b); // 让 a 的容量大
int ans = bfs();
if(ans)
{
cout<<ans<<endl;
}
else {
cout<<"NO"<<endl;
}
}
return 0;
}
忘了初始化!!!
改错改得脑阔疼!!!
不过
从别人的博客还发现了另类的做法
#include<cstdio>
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c),a+b+c)
{
a/=gcd(b,c);
if(a&1)printf("NO\n");
else printf("%d\n",a-1);
}
return 0;
}