Problem Description
给你三个数据,分别表示两个杯子的体积,和要你装出来的体积,两个杯子可以互相倒,也可以倒掉水,也可以装满水。要你输出最少的操作步骤,包括如何操作的。
代码:以前在自家OJ做过一样的题,但是那个题,不需要保存操作。。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<string>
using namespace std;
struct node
{
int lt, rt;
char s[15];
};
int a, b, c;
int vis[150][150];
node Pre[150][150];//用来保存路径
queue<node> q;
vector<string> p;//用来保存答案操作
void bfs()
{
q.push((node){0,0});
node t; int x, y, i;
while(!q.empty())
{
t = q.front();
q.pop();
if(t.lt == c || t.rt == c)//如果有那个杯子容量达到要求
{
printf("%d\n", vis[t.lt][t.rt] - 1);//输出操作次数
x = t.lt, y = t.rt;
while(x || y)//最初始状态退出循环
{
t.lt = x, t.rt = y;
p.push_back(Pre[t.lt][t.rt].s);//记录上一点的操作
x = Pre[t.lt][t.rt].lt, y = Pre[t.lt][t.rt].rt;
}
for(i = p.size() - 1; i >= 0; i--)//倒着输出
{
printf("%s\n", p[i].c_str());
}
return;
}
for(i = 0; i < 6; i++)//有六种情况
{
if(i == 0 && t.lt != a)//装满a
{
x = a; y = t.rt;
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;//操作步骤+1
Pre[x][y] = (node){t.lt, t.rt, "FILL(1)"};//存入上一个点的下标,和操作成这点的步骤
q.push((node){x, y});
}
}
if(i == 1 && t.rt != b)//装满b
{
x = t.lt; y = b;
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;
Pre[x][y] = (node){t.lt, t.rt, "FILL(2)"};
q.push((node){x, y});
}
}
if(i == 2)//a倒入b
{
if(t.lt + t.rt >= b)//倒满b
{
x = t.lt + t.rt - b; y = b;
}
else//倒不满b
{
x = 0; y = t.lt + t.rt;
}
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;
Pre[x][y] = (node){t.lt, t.rt, "POUR(1,2)"};
q.push((node){x, y});
}
}
if(i == 3)//b倒入a
{
if(t.lt + t.rt >= a)//倒满a
{
x = a; y = t.lt + t.rt - a;
}
else//不能倒满a
{
x = t.lt + t.rt; y = 0;
}
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;
Pre[x][y] = (node){t.lt, t.rt, "POUR(2,1)"};
q.push((node){x, y});
}
}
if(i == 4 && x != 0)//倒掉a
{
x = 0; y = t.rt;
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;
Pre[x][y] = (node){t.lt, t.rt, "DROP(1)"};
q.push((node){x, y});
}
}
if(i == 5 && y != 0)//倒掉b
{
x = t.lt; y = 0;
if(!vis[x][y])
{
vis[x][y] = vis[t.lt][t.rt] + 1;
Pre[x][y] = (node){t.lt, t.rt, "DROP(2)"};
q.push((node){x, y});
}
}
}
}
printf("impossible\n");
}
int main()
{
while(~scanf("%d %d %d", &a, &b, &c))
{
memset(vis, 0, sizeof(vis));
while(!q.empty()) q.pop();//初始化队列
vis[0][0] = 1;//最开始的状态标记一下
bfs();
}
return 0;
}