题目链接:POJ 3414 Pots
题目大意:
给你两个体积分别为(A)和(B)的容器,你对它们有三种操作,一种是装满其中一个瓶子,另一种是把其中一个瓶子的水都倒掉,还有一种就是把其中一个瓶子的水导入另一个瓶子中(可能会有剩余)。最后让你输出在能够得出体积为(C)的水的情况下操作的最小次数并且把过程输出。如果无法得出体积为(C)的水,则输出“impossible”。
题解:
模拟六种倒水情况并用BFS获取做小步数,用结构体中的prea、preb记录上一步的情况,并用递归输出整个过程,结构体中的step不仅记录步数,同时也起到标记的作用。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define ms(a, b) memset(a, b, sizeof(a))
#define MAXN 105
int A, B, C;
struct node {
int a, b, prea, preb, way, step;
} path[MAXN][MAXN];
queue <node> q;
void print(int a, int b) {
if (!path[a][b].a && !path[a][b].b) return;
print(path[a][b].prea, path[a][b].preb);
switch (path[a][b].way) {
case 1:
cout << "FILL(1)" << endl;
break;
case 2:
cout << "FILL(2)" << endl;
break;
case 3:
cout << "DROP(1)" << endl;
break;
case 4:
cout << "DROP(2)" << endl;
break;
case 5:
cout << "POUR(1,2)" << endl;
break;
case 6:
cout << "POUR(2,1)" << endl;
break;
}
}
void push(node t) {
if (!path[t.a][t.b].step) {
q.push(t);
path[t.a][t.b] = t;
}
}
void bfs() {
q.push(path[0][0]);
while (!q.empty()) {
node u = q.front();
q.pop();
if (u.a == C || u.b == C) {
cout << u.step << endl;
print(u.a, u.b);
return;
}
node v;
v.prea = u.a;
v.preb = u.b;
v.step = u.step + 1;
// 六种情况
if (u.a != A) {
v.a = A;
v.b = u.b;
v.way = 1;
push(v);
}
if (u.b != B) {
v.b = B;
v.a = u.a;
v.way = 2;
push(v);
}
if (u.a) {
v.a = 0;
v.b = u.b;
v.way = 3;
push(v);
}
if (u.b) {
v.a = u.a;
v.b = 0;
v.way = 4;
push(v);
}
if (u.a && u.b != B) {
if (u.a + u.b >= B) {
v.b = B;
v.a = u.a + u.b - B;
} else {
v.a = 0;
v.b = u.a + u.b;
}
v.way = 5;
push(v);
}
if (u.a != A && u.b) {
if (u.a + u.b >= A) {
v.a = A;
v.b = u.a + u.b - A;
} else {
v.a = u.a + u.b;
v.b = 0;
}
v.way = 6;
push(v);
}
}
cout << "impossible" << endl;
}
int main() {
ms(path, 0);
path[0][0].a = path[0][0].b = 0;
path[0][0].prea = path[0][0].preb = -1;
path[0][0].step = 0;
cin >> A >> B >> C;
bfs();
return 0;
}