当前位置: 代码迷 >> 综合 >> POJ - 3414 Pots
  详细解决方案

POJ - 3414 Pots

热度:41   发布时间:2023-12-17 02:53:47.0

这道题的题意是给你两个容器,问你通过容器A和容器B能获得容量为C的液体。其中操作有三种,fill(a):把a填满,drop(a):把a倒掉,pour(a,b):把a倒入b中。要求把操作顺序输出。

有很多种操作方式,我们一种一种遍历,直到出现结果为止,可以采取bfs的方式,这道题的难点在于怎么把路径输出。在bfs中,我们开始会选区队首的元素,通过队首的元素来获得队尾的元素,所以我们只需要在队尾标记队首就行,如果可行,我们顺着标记可以得到结果。代码如下:

#include <map>
#include <cstdio>
#include <cstring>using namespace std;const int N = 105;
int a, b, c, t;
int le, ri; //队首, 队尾
int v[N][N]; //判断这种情况是否出现过
int x[N * N], p[N * N], op[N * N], d[N * N]; //操作主体(A,B), 连接上个结点,操作类型(fill,drop,pour),操作次数
pair<int, int> q[N * N];void check(int i, int j, int o, int k)
{if(v[i][j]) return;v[i][j] = 1;p[ri] = le;op[ri] = o;x[ri] = k;d[ri] = d[le] + 1;q[ri++] = make_pair(i, j);
}int bfs()
{int ca, cb = le = ri = 0;q[ri++] = make_pair(0, 0);memset(v, 0, sizeof(v)), v[0][0] = 1;while(le < ri){ca = q[le].first, cb = q[le].second;if(ca == c || cb == c) return le;check(a, cb, 1, 1);                 //FILL(1);check(ca, b, 1, 2);                 //FILL(2);check(0, cb, 2, 1);                 //DROP(1);check(ca, 0, 2, 2);                 //DROP(2);if(ca > b - cb) check(ca - b + cb, b, 3, 1);else check(0, ca + cb, 3, 1);       //POUR(1,2);if(cb > a - ca) check(a, cb - a + ca, 3, 2);else check(ca + cb, 0, 3, 2);       //POUR(2,1);++le;}return 0;
}void print(int k)
{if(p[k] > 0)print(p[k]);if(op[k] == 1)printf("FILL(%d)\n", x[k]);if(op[k] == 2)printf("DROP(%d)\n", x[k]);if(op[k] == 3)printf("POUR(%d,%d)\n", x[k], 3 - x[k]);
}int main()
{int ans;while(~scanf("%d%d%d", &a, &b, &c)) {if(ans = bfs()) {printf("%d\n",d[ans]);print(ans);}else puts("impossible");}return 0;
}