题目链接:非常可乐 HDU - 1495
===================================================
非常可乐
Time Limit: 1000MS
Memory Limit: 32768 kB
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
思路:
- 在于必须一个容器为空
- 这里需要得到一半的水容量,设为x;三个容器容量分别为a,b,c;只有x能除尽gcd(a,b,c)才能成功;
===================================================
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int x,y,z,cnt;
bool fk[1000005];
struct node{
int u,v,w,step;
node(int uu,int vv,int ww,int ss):u(uu),v(vv),w(ww),step(ss) {};
};
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
bool bfs(){
queue<node> q;q.push(node(x,0,0,0));fk[x*10000] = false;
while(!q.empty()){
node p = q.front();q.pop();
int u = p.u , v = p.v , w = p.w,step = p.step;
//cout<<u<<" "<<v<<" "<<w<<" "<<step<<" "<<cnt<<endl;
if(u == cnt || v == cnt || w == cnt) {
step = (!u||!v||!w)?step:step+1;
cout<<step<<endl;return true;
}
int uu,vv,ww,tnt;
if(u){
uu = u+v>=y?u+v-y:0;
vv = u+v>=y?y:u+v;
ww = w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u+w>=z?u+w-z:0;
vv = v;
ww = u+w>=z?z:u+w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
if(v){
uu = u+v;
vv = 0;
ww = w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u;
vv = v+w>=z?v+w-z:0;
ww = v+w>=z?z:v+w;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
if(w){
uu = u+w;
vv = v;
ww = 0;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
uu = u;
vv = v+w>=y?y:v+w;
ww = v+w>=y?v+w-y:0;
tnt = uu*10000+vv*100+ww;
if(fk[tnt]){fk[tnt]=false;q.push(node(uu,vv,ww,step+1));}
}
}
return false;
}
int main()
{
while(cin>>x>>y>>z){
if(x==0&&y==0&&z==0) break;
if(x%2) {puts("NO");continue;}
cnt = x/2;memset(fk,true,sizeof fk);
if(cnt%gcd(x,gcd(y,z))) {puts("NO");continue;}
if(!bfs()) puts("NO");
}
return 0;
}
===================================================
#include <iostream>
#include <queue>
#include <cstring>
#include <string.h>
#include <cstdio>
using namespace std;
int s, n, m;
bool cp[101][100][100];
struct node{
int x,y,z,num;
node(int xx,int yy,int zz,int nn):x(xx),y(yy),z(zz),num(nn) {};
};
node e = node(0,0,0,0);
bool bfs(){
int tt = s / 2;
queue<node> q;
q.push(node(s,0,0,0));
cp[s][0][0] = true;
while(!q.empty()){
int a,b,c,x,y,z;
e = q.front();q.pop();
a = e.x , b = e.y , c = e.z;
//cout<<a<<" "<<b<<" "<<c<<endl;
if(a == tt|| b == tt || c == tt){
if(!a||!b||!c) cout<<e.num<<endl;
else cout<<e.num+1<<endl;
return true;
}
for(int i=0;i<6;i++){
if(i==0) if(b==n) continue;else x = a - min(a ,n - b) , y = b + min(a , n - b) , z = c;
else if(i==1) x = a + b , y = 0 , z = c;
else if(i==2) if(c==m) continue;else x = a - min(a ,m - c) , y = b , z = c + min(a ,m - c);
else if(i==3) x = a + c , y = b , z = 0;
else if(i==4) if(b==n) continue;else x = a , y = b + min(c ,n - b) , z = c - min(c ,n - b);
else if(i==5) if(c==m) continue;else x = a , y = b - min( b ,m - c ), z = c + min( b ,m - c );
if(cp[x][y][z]) continue;cp[x][y][z] = true;
q.push(node(x,y,z,e.num+1));
}
}
return false;
}
int main()
{
while(cin>>s>>n>>m&&s){
if(s%2) {puts("NO");continue;}
memset(cp,false,sizeof cp);
if(!bfs()) puts("NO");
}
return 0;
}