这题让我想起了杭电的那一道三个可乐罐的题目,那一题好像只要输出次数就可以了,而这里则需要将所有的路径全部输出出来,这样的话,单纯的BFS则会在状态的保留上会出现大量的空间冗余。于是这题在考虑到搜索空间一定的情况下,并且这些空间具有只访问一次的特性,因此,可以直接对题目进行构图,也就是相当于BFS中不对队列进行删除元素。通过一个二维数组来存储传递路径,再通过一个二维数组来存储父亲结点。
代码如下:
#include <cstdlib> #include <cstring> #include <cstdio> #include <queue> #include <algorithm> using namespace std; // 直接用G[i][j]来进行构图,P[i][j]记录父亲 int x, y, z, G[105][105], P[105][105], endx, endy; struct Node { int x, y, ti; }info, pos; queue<Node>q; char ss[10][15] = { "", "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)", }; /* 定义: 1.FILL(1) 2.FILL(2) 3.DROP(1) 4.DROP(2) 5.POUR(1,2) 6.POUR(2,1) 一共六种操作 */ bool push(int op) { if (!G[info.x][info.y]) { q.push(info); G[info.x][info.y] = op; P[info.x][info.y] = pos.x * 1000 + pos.y; if (info.x == z || info.y == z) { endx = info.x, endy = info.y; return true; } } return false; } int bfs(int &step) { while (!q.empty()) q.pop(); bool finish = false; info.x = 0, info.y = 0, info.ti = 0; G[info.x][info.y] = -1; q.push(info); while (!q.empty()) { pos = q.front(); q.pop(); info.ti = pos.ti + 1; info.x = x, info.y = pos.y; finish |= push(1); info.x = pos.x, info.y = y; finish |= push(2); info.x = 0, info.y = pos.y; finish |= push(3); info.x = pos.x, info.y = 0; finish |= push(4); info.x = pos.x - min(pos.x, y - pos.y); info.y = pos.y + pos.x - info.x; finish |= push(5); info.y = pos.y - min(pos.y, x - pos.x); info.x = pos.x + pos.y - info.y; finish |= push(6); if (finish) { step = info.ti; break; } } return finish; } void dfs(int a, int b) { if (a || b) { dfs(P[a][b]/1000, P[a][b]%1000); puts(ss[G[a][b]]); } } void display(int &step) { int a = endx, b = endy; printf("%d\n", step); dfs(a, b); } int main() { int step; while (scanf("%d %d %d", &x, &y, &z) == 3) { memset(G, 0, sizeof (G)); if (bfs(step)) { display(step); } else { puts("impossible"); } } return 0; }