搜索 BFS 非常可乐 HDU - 1495
**题目链接:**https://vjudge.net/problem/HDU-1495
题意:
现在有一杯可乐和两个杯子,是否可以把这一杯可乐分成体积完全相等的两份。
你可以将三个杯子中的可乐任意倒到其余两个杯子中但是操作结束之后你要知道每个杯子到底还有多少可乐,所以怎么倒很关键,你能随便倒这样你就不知道你是否将他成功分开了。
如果可以输出最少操作数目,否则输出NO。
思路:
我们就广搜枚举每种状态下的操作,三个瓶子为了在操作之后知道每个瓶子的体积 所以只可以每次将一个瓶子里的可乐全部倒入另一个杯子或者将可乐倒到另一个杯子时你这个杯子还没倒完,那个杯子已经满了,这两种情况都是合理的操作。
用一个三维数组表示这三个瓶子时时刻刻的状态。
代码在实现每次模拟操作过程时量很大 , 请务必认真仔细不然很难找到问题。
具体看一下代码里面的注释。
ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int dis[105][105][105]; //到这一步最少的操作次数
int vis[105][105][105]; //标记是否进队列
struct node{
int x,y,z;
};
int bfs(int ss,int nn,int mm){
node now,temp;
queue<node>q;
now.x=ss;now.y=0;now.z=0;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
q.push(now);
vis[ss][nn][mm]=1;
while(!q.empty()){
now=q.front();
q.pop();
if((now.x==0&&now.y==ss/2&&now.z==ss/2)||(now.x==ss/2&&now.y==0&&now.z==ss/2)||(now.x==ss/2&&now.y==ss/2&&now.z==0)){
return dis[now.x][now.y][now.z];
} //这是最终希望的目标
for(int i=0;i<3;i++){ //3次操作分别对应第1,2,3个杯子。
if(i==0){ //第一个杯子倒给其他两个杯子
if(now.x==0)continue;
if(now.x>=nn-now.y){ //第一个倒给第二个
temp.x=now.x-(nn-now.y);
temp.y=nn;
temp.z=now.z;
}
else{
temp.x=0;
temp.y=now.y+now.x;
temp.z=now.z;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
if(now.x>=mm-now.z){ //第一个倒给第三个
temp.x=now.x-(mm-now.z);
temp.y=now.y;
temp.z=mm;
}
else{
temp.x=0;
temp.y=now.y;
temp.z=now.x+now.z;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
}
if(i==1){ //第二个杯子倒给其他两个杯子
if(now.y==0)continue;
if(now.y>=ss-now.x){ //第二个倒给第一个
temp.x=ss;
temp.y=now.y-(ss-now.x);
temp.z=now.z;
}
else{
temp.x=now.x+now.y;
temp.y=0;
temp.z=now.z;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
if(now.y>=mm-now.z){ //第二个倒给第三个
temp.x=now.x;
temp.y=now.y-(mm-now.z);
temp.z=mm;
}
else{
temp.x=now.x;
temp.y=0;
temp.z=now.y+now.z;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
}
if(i==2){ //第三个杯子倒给其他两个杯子
if(now.z==0)continue;
if(now.z>=ss-now.x){ //第三个倒给第一个
temp.x=ss;
temp.y=now.y;
temp.z=now.z-(ss-now.x);
}
else{
temp.x=now.z+now.x;
temp.y=now.y;
temp.z=0;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
if(now.z>=nn-now.y){ //第三个倒给第二个
temp.x=now.x;
temp.y=nn;
temp.z=now.z-(nn-now.y);
}
else{
temp.x=now.x;
temp.y=now.y+now.z;
temp.z=0;
}
//cout<<temp.x<<" "<<temp.y<<" "<<temp.z<<endl;
if(!vis[temp.x][temp.y][temp.z]){
dis[temp.x][temp.y][temp.z]=dis[now.x][now.y][now.z]+1;
q.push(temp);
vis[temp.x][temp.y][temp.z]=1;
}
}
}
}
return -1;
}
int main()
{
int s,n,m;
while(~scanf("%d%d%d",&s,&n,&m)&&s+n+m){
int ans=bfs(s,n,m);
if(ans==-1){
printf("NO\n");
}
else{
printf("%d\n",ans);
}
}
}