做这题的时候,没有思路,觉得暴力的话,状态可能会爆炸。
但是每一个状态,最多只有六个后继状态,并且数据量很小,可以使用bfs枚举得出最短路
。
搜索的时候,怎么判断该状态
是否已经经过了呢,可以使用 visit数组。因为每个瓶子最大容量是 30 两个瓶子的组合才 900 ,容量空间非常小。
所以这题最重要的就是关注到状态转移
和 visit 数组
。
另外还有一点就是学习了如何打印 bfs路径
。
可以使用一维数组存储所有的枚举过的状态,然后使用链式前向星的思想,记录每一个节点的前驱结点。
关键点在于每一个 节点的父亲节点是唯一的,每一个节点的孩子节点却有多个。
这是一个多叉图,而不是网状图。
#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
int va,vb,vc;
struct node
{
int father;
int a;
int b;
int x; //操作几
int y; //对谁操作
}num[10005];
vector<int> path;
queue<int> qu;
int vis[105][105];
int counts;
int flag;
void bfs()
{
counts=0;
num[counts].a = 0;
num[counts].b = 0;
num[counts].father = -1;
qu.push(counts);
vis[num[counts].a][num[counts].b] = 1; //如果这个点已经进入队列就不用再进队了 因为在此之前 一定步数更少
counts++;
while(!qu.empty())
{
int p = qu.front();
node f = num[p];
qu.pop();
if(f.a==vc||f.b==vc)
{
flag =p;
break;
}
//操作 a
//填满
if(f.a< va&&vis[va][f.b]!=1)
{
num[counts].a = va;
num[counts].b = f.b;
num[counts].father =p ;
num[counts].x = 1;
num[counts].y = 0;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
//清空
if(f.a >0 &&vis[0][f.b]!=1)
{
num[counts].a = 0;
num[counts].b = f.b;
num[counts].father = p;
num[counts].x = 2;
num[counts].y = 0;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
// a -> b
if(f.a >0 &&f.b<vb)
{
int aa;
int bb;
if(f.a > vb-f.b)
{
aa = f.a -vb+f.b;
bb = vb;
}
else
{
aa = 0;
bb = f.a+f.b;
}
if(vis[aa][bb]!=1)
{
num[counts].a = aa;
num[counts].b = bb;
num[counts].father = p;
num[counts].x = 3;
num[counts].y = 0;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
}
//操作 b
//填满
if(f.b<vb &&vis[f.a][vb]!=1)
{
num[counts].a = f.a;
num[counts].b = vb;
num[counts].father = p;
num[counts].x = 1;
num[counts].y = 1;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
//清空
if(f.b >0 &&vis[f.a][0]!=1)
{
num[counts].a = f.a;
num[counts].b = 0;
num[counts].father = p;
num[counts].x = 2;
num[counts].y = 1;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
// b -> a
if(f.b >0 &&f.a<va)
{
int aa;
int bb;
if(f.b > va-f.a)
{
aa = va;
bb = f.b - va+f.a;
}
else
{
aa = f.a+f.b;
bb = 0;
}
if(vis[aa][bb]!=1)
{
num[counts].a = aa;
num[counts].b = bb;
num[counts].father = p;
num[counts].x = 3;
num[counts].y = 1;
qu.push(counts);
vis[num[counts].a][num[counts].b]=1;
counts++;
}
}
}
while(!qu.empty())qu.pop();
}
string op[3] = {"FILL","DROP","POUR"};
void shows(int i)
{
int x = num[i].x;
int y = num[i].y;
if(x==1)
{
if(y==0)cout<<"FILL(1)"<<endl;
else cout<<"FILL(2)"<<endl;
}else if(x==2){
if(y==0) cout<<"DROP(1)"<<endl;
else cout<<"DROP(2)"<<endl;
}else if(x==3){
if(y==0) cout<<"POUR(1,2)"<<endl;
else cout<<"POUR(2,1)"<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
while(cin>>va>>vb>>vc)
{
flag =-1;
memset(vis,0,sizeof(vis));
bfs();
if(flag == -1)
{
cout<<"impossible"<<endl;
}else{
path.clear();
while(flag!=-1)
{
path.push_back(flag);
flag = num[flag].father;
}
cout<<path.size()-1<<endl;
for(int i = path.size()-1;i>=0;i--)
{
shows(path[i]);
}
}
}
return 0;
}