题意:
“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列开始,不应该有空行或任何尾随空格。
思路:
倒水分为以下几种情况:1. 将A杯中的水倒空 2. 将B杯的水倒空 3. 向A杯中倒水 1)将A杯倒满,B杯水量不变 2)从B中向A杯倒水 a. 把B杯倒空 b. 把A杯倒满 4. 向B杯中倒水 1)将B杯倒满,A杯水量不变 2)从A中向B杯倒水 a. 把A杯倒空 b. 把B杯倒满
相当于层次遍历,一种操作完成后,将水杯状态放入入队列中,从队首取水杯状态再重复进行上述操作。
map<Status, Status> 记录一种状态是由哪种状态变化来的(感觉类似父节点),在由初始状态到规定状态的过程中,每一种状态都有其from的状态,最后由要求的最终状态通过递归输出变换的过程。
总结:
bfs的一种应用,使用from由最终状态进行了操作过程的回溯。
代码:
#include<iostream>
#include<queue>
#include<string>
#include<map>
using namespace std;
struct Status
{
int a, b;
string step;
bool operator<(const Status &s) const
{
return a!=s.a ? a<s.a : b<s.b;
}
};
queue<Status> Q; //记录水杯状态
map<Status, Status> from;
void renew(Status &s, Status &t)
{
if ( from.find(t) == from.end() )
{ // 特判合法,加入队列
from[t] = s;
Q.push(t);
}
}
//输出方案
void print(Status &m)
{
if ( from.find(m) == from.end() || (m.a == 0&&m.b==0) )
return;
print(from[m]); // 递归
cout<<m.step<<endl;
}
void bfs(int A, int B, int C)
{
// 起点, 两杯水都空
Status s,t;
s.a=0; s.b=0;s.step="//";
Q.push(s);
while (!Q.empty())
{
// 取队首
s = Q.front(); Q.pop();
// 特判到达终点
if (s.a == C || s.b == C) {
print(s); // 输出方案
cout<<"success"<<endl;
return;
}
// 倒空A杯的水
if (s.a > 0) {
t.a = 0; // 倒空
t.b = s.b;// b 杯不变
t.step="empty A";
renew(s, t);
}
// 倒空B杯的水
if (s.b > 0) {
t.b = 0; // 倒空
t.a = s.a;// a 杯不变
t.step="empty B";
renew(s, t);
}
//向A杯中倒水
if (s.a < A)
{
//倒满A杯
t.a = A;
t.b = s.b;
t.step="fill A";
renew(s, t);
//从B杯中倒入
if (s.b != 0)
{
if (s.a + s.b <= A)
{ //B杯倒入A杯中且B杯倒空
t.a = s.a + s.b;
t.b = 0;
t.step="pour B A";
renew(s, t);
} else
{ //B杯倒入A杯中且A杯倒满
t.a = A;
t.b = s.a + s.b - A;
t.step="pour B A";
renew(s, t);
}
}
}
//向B杯中倒水
if (s.b < B)
{
//倒满B杯
t.a = s.a;
t.b = B;
t.step="fill B";
renew(s, t);
//从A中倒入
if (s.a != 0)
{
//B杯倒入A杯中且B杯倒空
if (s.a + s.b <= B)
{
t.a = 0;
t.b = s.a + s.b;
t.step="pour A B";
renew(s, t);
} else //B杯倒入A杯中且A杯倒满
{
t.a = s.a + s.b - B;
t.b = B;
t.step="pour A B";
renew(s, t);
}
}
}
}
}
int main()
{
int A,B,C;
while(cin>>A>>B>>C)
bfs(A,B,C);
return 0;
}