链接:点击打开链接
题意:给你三个容器让你平分可乐,求最少的步数。
思路:一看到求最少步数,就想到了广搜,但是没有思路,但看别人分情况,瞬间就明白啦。可以S->N,S->M,N->S,N->M,M->S,M->N这六种情况讨论就行,每种又有倒完和倒不完两种情况,直到出现两个容器都有S/2,这就是最少步数。但S是奇数时是不能平分的,三个容器的容积都是整数。不一定偶数就能可以平分,我因为少了这个条件,而WA一次。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int s,n,m;
struct node{
int a,b,c;
int count;
};
bool vis[110][110][110];
void bfs(){
int i;
queue<node>Q;
node q,p;
p.a=s;
p.b=0;
p.c=0;
p.count=0;
memset(vis,false,sizeof(vis));
vis[p.a][p.b][p.c]=true;
Q.push(p);
while(!Q.empty()){
p=Q.front();
Q.pop();
if((p.a==s/2&&p.b==s/2)||(p.a==s/2&&p.c==s/2)||(p.b==s/2&&p.c==s/2)){
printf("%d\n",p.count);
return;
}
if(p.a!=0){
if(p.a>n-p.b){//s->n
q.a=p.a-(n-p.b);
q.b=n;
q.c=p.c;
q.count=p.count+1;
}
else{
q.a=0;
q.b=p.b+p.a;
q.c=p.c;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
if(p.a>m-p.c){//s->m
q.a=p.a-(m-p.c);
q.b=p.b;
q.c=m;
q.count=p.count+1;
}
else{
q.a=0;
q.b=p.b;
q.c=p.c+p.a;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
}
if(p.b!=0){
if(p.b>s-p.a){//n->s
q.a=s;
q.b=p.b-(s-p.a);
q.c=p.c;
q.count=p.count+1;
}
else{
q.a=p.a+p.b;
q.b=0;
q.c=p.c;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
if(p.b>m-p.c){//n->m
q.a=p.a;
q.b=p.b-(m-p.c);
q.c=m;
q.count=p.count+1;
}
else{
q.a=p.a;
q.b=0;
q.c=p.c+p.b;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
}
if(p.c!=0){
if(p.c>s-p.a){//m->s
q.a=s;
q.b=p.b;
q.c=p.c-(s-p.a);
q.count=p.count+1;
}
else{
q.a=p.a+p.c;
q.b=p.b;
q.c=0;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
if(p.c>n-p.b){//m->n
q.a=p.a;
q.b=n;
q.c=p.c-(n-p.b);
q.count=p.count+1;
}
else{
q.a=p.a;
q.b=p.b+p.c;
q.c=0;
q.count=p.count+1;
}
if(!vis[q.a][q.b][q.c]){
vis[q.a][q.b][q.c]=true;
Q.push(q);
}
}
}
printf("NO\n");
return;
}
int main(){
while(~scanf("%d %d %d",&s,&n,&m)){
if(s==0&&n==0&&m==0)
break;
if(s%2==1)
printf("NO\n");
else
bfs();
}
return 0;
}