真心有点佩服自己了,一个这么明显的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;
}