题目链接:http://poj.org/problem?id=3414
由于一直没有好好掌握搜索, 所以经常遇到搜索题就挂了,老师让我们默写我都写不出来。为了准备蓝桥杯以及之后的比赛,我下定决心好好学, 恢复以前的状态。
题意:bfs + 路径打印, 六种状态:A fill, A drop, B fill, B drop, A pour B, B pour A, 广搜不多说,直接上代码。打印路径: 记录A B剩余水的状态, 以上一次A B 剩余水量作为其前区节点, 定义一个结构体储存剩余水量, 每一次操作状态, 以及步数。 我做这题时收获不小, 这道题让我掌握了一点bfs, 还有就是遇到了一个坑点, 然后一直很揪心。原来的方法,每一次第一个输出的总是fill(1),花了好久时间发现问题。 问题:由于广搜的起点并不是六种操作, 所以第一步的状态就不能常规解决。 后来我想到在dfs打印路径时, 可以做一个判断, 因为刚开始A B 都是没有水的, 所以第一步操作只能是 fill(1)或fill(2),于是输出前做一个判断就OK了。
代码:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 1e2 + 5;
struct pot {
int k1, k2, op;
};
struct path{
int x, y, op, step;
}path[maxn][maxn];
char str[][10] = { "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(2,1)", "POUR(1,2)"};
int A, B, C;
bool judge[maxn][maxn];
void my_clear() {
struct path h = {0, 0, 0, 0};
memset(judge, 0, sizeof(judge));
for (int i = 0; i < maxn; i++)
for (int j = 0; j < maxn; j++)
path[i][j]= h;
}
// 递归打印路径
void dfs(int x, int y) {
int a = path[x][y].x;
int b = path[x][y].y;
if (path[x][y].step == 0) { //输出第一次操作
if (a == A)
cout << str[0] << endl;
if (b == B)
cout << str[1] << endl;
return;
}
dfs(a, b);
cout << str[path[x][y].op]<< endl;
}
void BFS(int v1, int v2, int L) {
queue <pot> wat;
pot start = {0, 0, 0};
judge[0][0] = true;
wat.push(start);
while (!wat.empty()) {
pot tep = wat.front();
wat.pop();
int temp;
if (tep.k1 == L || tep.k2 == L) {
cout << path[tep.k1][tep.k2].step << endl;
dfs(tep.k1, tep.k2);
return ;
}
for (int i = 0; i < 6; i++) {
switch(i) {
/*6种状态*/
case 0 : start.k1 = v1, start.k2 = tep.k2; break; //A fill
case 2 : start.k1 = 0, start.k2 = tep.k2; break; //A empty
case 1 : start.k1 = tep.k1; start.k2 = v2; break; //B fill
case 3 : start.k1 = tep.k1; start.k2 = 0; break; //B empty
case 5 : temp = tep.k1 + tep.k2 - v2; //A -> B
if (temp > 0) {
start.k1 = temp;
start.k2 = v2;
}
else {
start.k1 = 0;
start.k2 = tep.k1 + tep.k2;
}
break;
case 4 : temp = tep.k1 + tep.k2 - v1; // B -> A
if (temp > 0) {
start.k2 = temp;
start.k1 = v1;
}
else {
start.k2 = 0;
start.k1 = tep.k1 + tep.k2;
}
break;
}
if (!judge[start.k1][start.k2]) {
path[start.k1][start.k2].x = tep.k1;
path[start.k1][start.k2].y = tep.k2;//记录前驱结点
path[start.k1][start.k2].op = i;
path[start.k1][start.k2].step = path[tep.k1][tep.k2].step + 1;
judge[start.k1][start.k2] = true;
wat.push(start);
}
}
}
cout << "impossible" << endl;
}
int main()
{
while (cin >> A >> B >> C) {
BFS(A, B, C);
my_clear();
}
return 0;
}