题目传送门
话说BFS的搜索树我觉得还是挺巧妙的,这道题用到了用struct入队,还是相对来说比较巧妙。
首先这道题每一个操作步骤都有6个分支:
1.装满1
2.装满2
3.倒空1
4.倒空2
5.1倒2
6.2倒1
六个搜索分支因为只有六种情况,所以可以用一个string数组来存储这六种状态,只用记录这个状态所对应的数组下标的顺序,当然题目读到这,我还是没有立刻想到用bfs来完成本题,接下来,题目要求搜索到步骤最小的情况,因此必是bfs。
既然是BFS搜索树,那必然是每种情况都先入队,在每一种情况的最先开始的时候用一个新定义的结构体,来存这些状态,因为这六种不同的状态在本过程是互斥的,因此不能全权存储。
当然本题在每一种不同的情况的易错点就在于:先运算,再赋值要不然就会感受到Wonderful Accept的快感。
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
string s[10]={" ","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
bool st[210][210];
struct node{
int a,b;
int num;
int t[210];
}bo;
queue<node>q;
int main(){
// cout<<s[1]<<endl;
int aa,bb,c;
cin>>aa>>bb>>c;
bo.a=0;
bo.b=0;
bo.num=0;
q.push(bo);
st[0][0]=true;
while(q.size()){
//cout<<"ok"<<endl;
node now=q.front();
q.pop();
// cout<<now.a<<' '<<now.b<<endl;
if(now.a==c||now.b==c){
printf("%d\n",now.num);
for(int i=1;i<=now.num;i++){
//cout<<now.t[i]<<endl;
cout<<s[now.t[i]]<<endl;
}return 0;
}
for(int i=1;i<=6;i++){
node af=now;af.num++;
// cout<<af.num<<endl;
if(i==1&&af.a!=aa){
af.a=aa;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=1;
q.push(af);
}
}else if(i==2&&af.b!=bb){
af.b=bb;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=2;
q.push(af);
}
}else if(i==3&&af.a!=0){
af.a=0;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=3;
q.push(af);
}
}else if(i==4&&af.b!=0){
af.b=0;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=4;
q.push(af);
}
}else if(i==5){
// cout<<"555or:"<<" "<<af.a<<" "<<af.b<<endl;
if(bb-af.b>=af.a){
af.b+=af.a;af.a=0;
}else {
af.a+=af.b-bb;
af.b=bb;
}
// cout<<"555end:"<<" "<<af.a<<" "<<af.b<<endl;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=5;
q.push(af);
}
}else if(i==6){
// cout<<"666or:"<<" "<<af.a<<" "<<af.b<<endl;
if(aa-af.a>=af.b){
af.a+=af.b;af.b=0;
}else {
af.b+=af.a-aa;
af.a=aa;
}
// cout<<"666end:"<<" "<<af.a<<" "<<af.b<<endl;
if(!st[af.a][af.b]){
st[af.a][af.b]=true;
af.t[af.num]=6;
q.push(af);
}
}
}
}
printf("impossible\n");
return 0;
}