蓝桥杯预赛 分红酒问题 9 7 4 2

     真心有点佩服自己了,一个这么明显的BFS都A不出来,努力不够啊。

  题目:   

  有4个红酒瓶子,它们的容量分别是:9升, 7升, 4升, 2升
  开始的状态是 [9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。
  允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。这样的一次倒酒动作称为1次操作。
  假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?
  本题就是要求你编程实现最小操作次数的计算。
  输入:最终状态(逗号分隔)
  输出:最小操作次数(如无法实现,则输出-1)
例如:
输入:
9,0,0,0
应该输出:
0
输入:
6,0,0,3
应该输出:
-1
输入:
7,2,0,0
应该输出:
2

代码里面有解释,建议直接看代码。

其实这题很明显,BFS啊,唯一需要注意的就是状态的处理,不能盲目的搜。(我是用一个四维数组来存储状态的)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
typedef struct{
int bot[4];//瓶子的现状
int cou;//求最小步
}Node;
int vis[10][8][5][3];
int cap[4]={9,7,4,2};//瓶子的容量
int app[4];//瓶子的末状
int BFS()
{
  queue<Node> p;
  Node now,next;
  p.push((Node){{9,0,0,0},0});
  vis[9][0][0][0]=false;
  while(!p.empty())
  {
   now = p.front();
   p.pop();
   if(now.bot[0]==app[0]&&now.bot[1]==app[1]&&now.bot[2]==app[2]&&now.bot[3]==app[3])
    return now.cou;
   for(int i=0; i<4; ++i)//寻找倒的容器,所以不能为零。
   {
     if(now.bot[i]==0)
        continue;
    for(int e=0; e<4; ++e) //寻找装的容器
    {
     if(i==e||now.bot[e]==cap[e])
        continue;
     next.cou = now.cou+1;
     for(int j=0; j<4; ++j)
        next.bot[j]=now.bot[j];
     if(now.bot[i]+now.bot[e]>=cap[e])
     {
        next.bot[e]=cap[e];
        next.bot[i]=now.bot[i]+now.bot[e]-cap[e];
     }
     else
     {
       next.bot[i]=0;
       next.bot[e]=now.bot[i]+now.bot[e];
     }
     if(vis[next.bot[0]][next.bot[1]][next.bot[2]][next.bot[3]])
       {
        vis[next.bot[0]][next.bot[1]][next.bot[2]][next.bot[3]]=false;
        p.push(next);
       }
    }
   }
  }
  return -1;
}
int main()
{
    char m[4];
    while(cin>> app[0]>>m[1]>> app[1]>>m[2]>> app[2]>>m[3]>>app[3])
    {
     memset(vis,true,sizeof(vis));
    int sum = 0;
    for(int i=0; i<4; ++i)
      sum += app[i];
    if(sum != 9)
    {
      cout <<"-1"<<endl;
      continue;
    }
    int g = BFS();
    if(g<0)
     cout <<"-1"<<endl;
    else
        cout<<g<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值