倒水问题 “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
Notes
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。
分析:bfs。搜索每一种状态(水量),对于每一次操作,有以下几种可能:
- 倒空
- 装满
- 倒向另一杯,考虑(另一杯满)和(此杯必须非空)
模拟每种可能操作,对于操作后的状态,需要判断是否已经有过这种状态,需要将已有状态记录下来,采用map<state, state>
key值为操作之前的状态,value为操作之后的状态。判断和记录操作封装为refresh函数。
打印操作递归解决。
代码如下:
#include <iostream>
#include <map>
#include <queue>
using namespace std;
struct state
{
int a, b;
state(int A = -1,int B = -1)
{
a = A;
b = B;
}
bool operator<(const state& rhs) const
{
return a != rhs.a ? a < rhs.a : b < rhs.b;
}
};
map<state, state> from;
queue<state> q;
void print2(const state& s, const state& t)
{
if (s.a + s.b == t.a + t.b)
if (s.a > t.a)
cout << "pour A B" << endl;
else
cout << "pour B A" << endl;
else if(s.a + s.b < t.a + t.b)
if (s.a < t.a)
cout << "fill A" << endl;
else
cout << "fill B" << endl;
else if(s.a + s.b > t.a + t.b)
if (s.a > t.a)
cout << "empty A" << endl;
else
cout << "empty B" << endl;
}
void print(const state& s)
{
if (from.find(s) == from.end() || (s.a == 0 && s.b == 0))
{
return;
}
state t = from[s];
print(t);
print2(t, s);
//cout << s.a << ' ' << s.b << endl;
return;
}
void refresh(const state& s, const state& t)
{
if (from.find(t) == from.end())
{
from[t] = s;
q.push(t);
}
}
void bfs(int A, int B, int C)
{
q.push(state(0, 0));
while (!q.empty())
{
state s = q.front();
q.pop();
if (s.a == C || s.b == C)
{
print(s);
cout << "success" << endl;
return;
}
state t;
if (s.a > 0)
{
t.a = 0;
t.b = s.b;
refresh(s, t);
}
if (s.b > 0)
{
t.b = 0;
t.a = s.a;
refresh(s, t);
}
if (s.a < A)
{
t.a = A;
t.b = s.b;
refresh(s, t);
if (s.b > 0)
{
if (s.a + s.b < A)
{
t.a = s.a + s.b;
t.b = 0;
refresh(s, t);
}
else
{
t.a = A;
t.b = s.a + s.b - A;
refresh(s, t);
}
}
}
if (s.b < B)
{
t.a = s.a;
t.b = B;
refresh(s, t);
if (s.a > 0)
{
if (s.a + s.b < B)
{
t.b = s.a + s.b;
t.a = 0;
refresh(s, t);
}
else
{
t.b = B;
t.a = s.a + s.b - B;
refresh(s, t);
}
}
}
}
}
int main()
{
int a, b, c;
while(cin >> a >> b >> c)
bfs(a, b, c);
}
效果如下