题意:
给你两个杯子的容量 和 最后杯子中剩余水的容量。有三种操作方式
- FILL(i) 将第 i 个杯子装满水
- DROP(i) 将第 i 个杯子的水倒空
- POUR(i,j) 将第 i 个杯子中的水倒入第 j 个杯子中 可能有两种情况:(1) i 杯子中的水还没全倒入 j 杯子中 j 杯子就满了,此时 i 杯子中还有剩余,(2)i 杯子中的水全倒入 j 杯子中,j 杯子没有溢出。
思路:
一共有6种不同的操作,直接 bfs 就行。难的是如何将路径记录下来并输出。
参考了大佬的博客:https://blog.csdn.net/u012860063/article/details/37768979
方法是在结构体中用一个指针记录他的上一个状态,在找到结果时通过指针将他的每一步操作存到栈中。
此题与POJ - 1606 Jugs 相同
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int vis[110][110]; //记录当前状态是否已经到达过
int a,b,c,ans;
struct node
{
int x,y; //两个杯子分别有多少水
int step;
int flag; //操作
node *pre; //上一步操作的结构体
};
queue<node> q;
stack<int> s;
void bfs(int x,int y)
{
node h;
node w[1000]; //数组的地址不相同,所以不能用单个结构体变量(否则取地址时地址会相同)
h.x = x;
h.y = y;
h.step = 0;
h.flag = 0;
h.pre = NULL;
vis[h.x][h.y] = 1;
q.push(h);
int cnt = -1;
while(!q.empty())
{
w[++cnt] = q.front();
q.pop();
for(int i=1;i<=6;i++)
{
switch(i)
{
case 1: //FILL(1)
h.x = a;
h.y = w[cnt].y;
h.flag = 1;
break;
case 2: //FILL(2)
h.x = w[cnt].x;
h.y = b;
h.flag = 2;
break;
case 3: //DROP(1)
h.x = 0;
h.y = w[cnt].y;
h.flag = 3;
break;
case 4: //DROP(2)
h.x = w[cnt].x;
h.y = 0;
h.flag = 4;
break;
case 5: //POUR(1,2)
if(w[cnt].x > b-w[cnt].y)
{
h.x = w[cnt].x-(b-w[cnt].y);
h.y = b;
}
else
{
h.x = 0;
h.y = w[cnt].y+w[cnt].x;
}
h.flag = 5;
break;
case 6: //POUR(2,1)
if(w[cnt].y > a-w[cnt].x)
{
h.x = a;
h.y = w[cnt].y-(a-w[cnt].x);
}
else
{
h.x = w[cnt].x+w[cnt].y;
h.y = 0;
}
h.flag = 6;
break;
}
if(vis[h.x][h.y])
continue;
vis[h.x][h.y] = 1;
h.step = w[cnt].step+1;
h.pre = &w[cnt];
if(h.x==c || h.y==c)
{
ans = h.step;
while(h.pre)
{
s.push(h.flag);
h = *h.pre;
}
return ;
}
q.push(h);
}
}
}
void print()
{
while(!s.empty())
{
switch(s.top())
{
case 1:
printf("FILL(1)\n");
break;
case 2:
printf("FILL(2)\n");
break;
case 3:
printf("DROP(1)\n");
break;
case 4:
printf("DROP(2)\n");
break;
case 5:
printf("POUR(1,2)\n");
break;
case 6:
printf("POUR(2,1)\n");
break;
}
s.pop();
}
}
int main()
{
scanf("%d%d%d",&a,&b,&c);
ans = 0;
memset(vis,0,sizeof(vis));
bfs(0,0);
if(ans)
{
printf("%d\n",ans);
print();
}
else
printf("impossible\n");
return 0;
}