简单bfs,只是添加了个回溯,由于不像迷宫那样可以简单的记录每一个格子的上一步操作来回溯(这种更复杂和抽象一些:如果开个pair二维数组存入该点上一步,则需要再写一个函数来对应6种变换。如果用int记录6种变化,但不能方便地直接通过这个变换,而且如果该点由步骤pour(1,2 )走来,那上一步可能有多种情况,难以反推上一步的坐标,甚至根本无法反推)鉴于数据量也不大,就在每个点上都记录下所有的变换步骤(用string实现貌似即方便又快)。代码如下
#include <cstdio>
#include <iostream>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <ctime>
#include <algorithm>
using namespace std;
const int MAXN = 1e2+10;
typedef long long LL;
struct point
{
int a;
int b;
int step;
string paath;
point(int aa,int bb,int ss)
:a(aa),b(bb),step(ss)
{}
};
int A,B,C;
char path[][15] =
{
"FILL(1)"
,"FILL(2)"
,"DROP(1)"
,"DROP(2)"
,"POUR(1,2)"
,"POUR(2,1)"
};
bool vis[MAXN][MAXN];
int V[4];
void bfs()
{
point t(0,0,0);
queue<point> s;
s.push(t);
vis[0][0] = 1;
while(!s.empty())
{
t = s.front();
s.pop();
if( t.a == C || t.b == C )
{
printf("%d\n",t.step);
for(int i=0; i<t.step; ++i)
{
int apple = t.paath[i]-'0'; //转换成int
printf("%s\n",path[ apple ]);
}
return;
}
int a[4];
for(int i=1; i<=2; ++i)
{
for(int j=0; j<3; ++j)
{
int way;
a[1] = t.a;
a[2] = t.b;
if(j == 0 && a[i] < V[i])
{
i == 1 ? way = 0 : way = 1;
a[i] = V[i];//注满水
}
else if(j == 1 && a[i] > 0)
{
i == 1 ? way = 2 : way = 3;
a[i] = 0;//倒完水
}
else if(j == 2)
{
if(a[i] >= V[3-i] - a[3-i])
{
a[i] -= V[3-i] - a[3-i];
a[3-i] = V[3-i];
} //x到给y,且y可以被倒满
else
{
a[3-i] += a[i];
a[i] = 0;
} //不可以被倒满
i == 1 ? way = 4 : way = 5;
}
if(!vis[a[1]][a[2]])
{
vis[a[1]][a[2]] = 1;
//way = j*2 + i -1;(这样写最方便,但是没找到BUG的时候却把这个纠结了半天。。。
point shit(a[1], a[2], t.step + 1);
shit.paath = t.paath + (char)(way+'0');//记录这一步,注意别忘记加上t.paath了。。
s.push(shit);
}
}
}
}
puts("impossible");
return;
}
int main()
{
scanf("%d%d%d",&A,&B,&C);
V[1] = A, V[2] = B;
memset(vis,0,sizeof(vis));
bfs();
return 0;
}