6.3分可乐

在这里插入图片描述

#include <stdio.h>
#include <queue>
using namespace std;
struct node{//状态结构体 
 int x,y,z;//每个杯子中可乐的体积 s,n,m
 int t;//所需要时间 
};  
bool halfequal(int x,int y,int z,int c){
 return (x==float(c)/2&&y==float(c)/2)||(x==float(c)/2&&z==float(c)/2)||(y==float(c)/2&&z==float(c)/2); 
}
queue<node> q;//保存入度为0的节点  
bool mark[101][101][101];//标记数组,一旦处理完就标记其位置为true 
int atob(int &a,int sa,int &b,int sb){//倾倒函数,由初始可乐体积为a,总体积为sa的杯子往初始可乐体积为b,总体积为sb的杯子中倒可乐,到后两者体积为改变后的a,b
 if(sb-b>=a){//a的可乐可以全部到给b 
  b+=a; 
  a=0; 
 }else{//a的可乐到满b后还有剩余 
  a-=sb-b;
  b=sb;
 } 
}
int bfs(int a,int b,int c){//s n m
 while(!q.empty()){
  node nowp=q.front();//得到队头状态 
  q.pop();//弹出队头
  int x=nowp.x;
  int y=nowp.y;
  int z=nowp.z;//读出该状态的s,n,m对应的可乐体积 
  node tmp;  
  atob(x,a,y,b);//a向b倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true; 
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a)){
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数 
   }
   q.push(tmp); 
     }
  x=nowp.x;
  y=nowp.y;
  z=nowp.z; 
  atob(y,b,x,a);//b向a倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true;
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a)){
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数  
   }
   q.push(tmp);
  }
  x=nowp.x;
  y=nowp.y;
  z=nowp.z; 
  atob(x,a,z,c);//a向c倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true;
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a))
   {
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数 
      }
   q.push(tmp);
    }
  x=nowp.x;
  y=nowp.y;
  z=nowp.z; 
  atob(z,c,x,a);//c向a倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true; 
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a)){
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数 
   }
   q.push(tmp);
  }
  x=nowp.x;
  y=nowp.y;
  z=nowp.z; 
  atob(y,b,z,c);//b向c倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true; 
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a)){
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数 
   }
   q.push(tmp); 
  }
  x=nowp.x;
  y=nowp.y;
  z=nowp.z; 
  atob(z,c,y,b);//c向b倒
  if(!mark[x][y][z]){//若该体积状态未出现过 
   mark[x][y][z]=true; 
   tmp.x=x;
   tmp.y=y;
   tmp.z=z;
   tmp.t=nowp.t+1;//又倒了一次
   if(halfequal(x,y,z,a)){
    return tmp.t;//若该状态已经为平分状态,可直接返回该状态倒的次数 
   }
   q.push(tmp); 
  } 
    }
 return -1;//所有状态都找完都未找到出口坐标,返回-1 
}
int main(){
 int s,n,m;
 while(scanf("%d%d%d",&s,&n,&m)!=EOF&&!(s==0&&n==0&&m==0)){
  for(int i=0;i<s;i++)
   for(int j=0;j<n;j++)
    for(int k=0;k<m;k++){
     mark[i][j][k]=false;//初始化城堡数组即标记数组 
          }
  while(!q.empty()) q.pop();//清空队列
  mark[s][0][0]=true;//标记出发节点 
  node tmp;
  tmp.x=s;
  tmp.y=0;
  tmp.z=0;
  tmp.t=0;//初始只有大瓶可乐 
  q.push(tmp);//出发节点进栈
  int rec=bfs(s,n,m);
  if(rec!=-1) printf("%d\n\n",rec);
  else printf("NO\n\n"); 
 } 
 return 0;
}

7 4 3
4 1 3
0 0 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值