题目描述
倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。
Input
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
Output
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
Hint
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。
算法分析
倒水问题(隐式图问题)可以用BFS记录可达的状态。另外,可以用类似A题的思路,记录前驱状态,之后递归输出,便可显式输出状态转移过程。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
struct Status
{
int a,b; //A瓶水量与B瓶水量
int type; //变换到当前状态的操作类型
bool operator < (const Status &s) const
{
if(a != s.a) return a < s.a;
else return b < s.b;
} //重载<
};//状态
queue<Status> Q; //BFS队列
map<Status, Status> from; //记录前置状态
void output(Status &p)
{
//递归输出
if(from.find(p) == from.end() || (p.a == 0 && p.b == 0)) //无前置状态或A、B瓶均没水
{
//printf("<%d,%d>",p.a,p.b);
return;
}
output(from[p]); //递归
//输出部分
if(p.type == 1) printf("empty A\n");
else if(p.type == 2) printf("empty B\n");
else if(p.type == 3) printf("fill A\n");
else if(p.type == 4) printf("pour B A\n");
else if(p.type == 5) printf("fill B\n");
else if(p.type == 6) printf("pour A B\n");
//printf(" |<%d,%d> |\n",p.a,p.b);
}
//记录两个状态直接的转换类型
void refresh(Status &s, Status &t,int type)
{
if(type == 1) t.type = 1;
else if(type == 2) t.type = 2;
else if(type == 3) t.type = 3;
else if(type == 4) t.type = 4;
else if(type == 5) t.type = 5;
else if(type == 6) t.type = 6;
if(from.find(t) == from.end())
{
from[t] = s;
Q.push(t);
}
}
void bfs(int A, int B, int C)
{
Status s,t; //s表示当前状态,t表示下一状态
s.a = s.b = 0;
Q.push(s);
while(!Q.empty())
{
s = Q.front();
Q.pop();
if(s.a == C || s.b == C) //A瓶或B瓶内水量为C
{
output(s);
return;
}
// 倒空A
if(s.a > 0)
{
t.a = 0;
t.b = s.b;
refresh(s, t, 1);
}
// 倒空B
if(s.b > 0)
{
t.b = 0;
t.a = s.a;
refresh(s, t, 2);
}
//倒满A
if(s.a < A)
{
t.a = A;
t.b = s.b;
refresh(s, t, 3);
if(s.b != 0)
{
//B倒入A
if(s.a + s.b <= A)
{
t.a = s.a + s.b;
t.b = 0;
refresh(s, t, 4);
}
else
{
t.a = A;
t.b = s.a + s.b - A;
refresh(s, t, 4);
}
}
}
//倒满B
if(s.a < B)
{
t.a = s.a;
t.b = B;
refresh(s, t, 5);
if(s.a != 0)
{
//A倒入B
if(s.a + s.b <= B)
{
t.a = 0;
t.b = s.a + s.b;
refresh(s, t, 6);
}
else
{
t.a = s.a + s.b - B;
t.b = B;
refresh(s, t, 6);
}
}
}
}
}
//初始化BFS队列
void clear(queue<Status> & q)
{
queue<Status> empty;
swap(empty, q);
}
int main()
{
int a,b,c;
while(~scanf("%d%d%d",&a,&b,&c))
{
//初始化
clear(Q);
from.clear();
bfs(a, b, c);
printf("success\n");
}
return 0;
}