[POJ-3414]
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
DROP(i) empty the pot i to the drain;
POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
using namespace std;
#define ll long long
#define lb long double
#define INF 0x3f3f3f3f
#define maxn 101 * 101 + 5
bool book[maxn];
int n, m, k, ans = -1, ex, ey, cnt, ei, ej;
struct node{
int x;
int y;
int d;
int vi;
int vj;
}last[105][105], anss[105];
int f(int a, int b){
return a * 101 + b;
}
void bfs(){
memset(book, 0, sizeof(book));
book[0] = 1;
node st;
st.x = 0; st.y = 0; st.d = 0;
queue<node> que;
que.push(st);
while(!que.empty()){
node cur = que.front();
que.pop();
if(cur.x == k || cur.y == k){
ans = cur.d; ex = cur.x; ey = cur.y; ei = cur.vi; ej = cur.vj;
break;
}
for(int i = 1 ; i <= 3 ; ++ i){
node temp;
if(i == 1){
for(int j = 1 ; j <= 2 ; ++ j){
if(j == 1){//FILL(1)
temp.x = n; temp.y = cur.y;
}
if(j == 2){//FILL(2)
temp.x = cur.x; temp.y = m;
}
if(!book[f(temp.x, temp.y)]){
temp.d = cur.d + 1; book[f(temp.x, temp.y)] = 1; temp.vi = i; temp.vj = j; que.push(temp);
last[temp.x][temp.y].x = cur.x; last[temp.x][temp.y].y = cur.y;
last[temp.x][temp.y].vi = i; last[temp.x][temp.y].vj = j;
}
}
}
if(i == 2){//POUR(2,1)
for(int j = 1 ; j <= 2 ; ++ j){
if(j == 1){//POUR(1,2)
if(cur.x <= m - cur.y){
temp.x = 0; temp.y = cur.x + cur.y;
}
else{
temp.x = cur.x - (m - cur.y); temp.y = m;
}
}
if(j == 2){//POUR(2,1)
if(cur.y <= n - cur.x){
temp.y = 0; temp.x = cur.y + cur.x;
}
else{
temp.y = cur.y - (n - cur.x); temp.x = n;
}
}
if(!book[f(temp.x, temp.y)]){
temp.d = cur.d + 1; book[f(temp.x, temp.y)] = 1; temp.vi = i; temp.vj = j; que.push(temp);
last[temp.x][temp.y].x = cur.x; last[temp.x][temp.y].y = cur.y;
last[temp.x][temp.y].vi = i; last[temp.x][temp.y].vj = j;
}
}
}
if(i == 3){//DROP(1)
for(int j = 1 ; j <= 2 ; ++ j){
if(j == 1){
temp.x = 0; temp.y = cur.y;
}
if(j == 2){
temp.x = cur.x; temp.y = 0;
}
if(!book[f(temp.x, temp.y)]){
temp.d = cur.d + 1; book[f(temp.x, temp.y)] = 1; temp.vi = i; temp.vj = j; que.push(temp);
last[temp.x][temp.y].x = cur.x; last[temp.x][temp.y].y = cur.y;
last[temp.x][temp.y].vi = i; last[temp.x][temp.y].vj = j;
}
}
}
//记录路径 i, j
//last[temp.x][temp.y].x = i; last[temp.x][temp.y].y = j;
}
}
}
int main()
{
scanf("%d %d %d", &n, &m, &k);
bfs();
//anss[++cnt].x = ex; anss[cnt].y = ey; anss[cnt].vi = ei; anss[cnt].vj = ej;
while(ex !=0 || ey != 0){
int tempx = ex, tempy = ey;
ex = last[tempx][tempy].x; ey = last[tempx][tempy].y; ei = last[tempx][tempy].vi; ej = last[tempx][tempy].vj;
anss[++ cnt].x = ex; anss[cnt].y = ey; anss[cnt].vi = ei; anss[cnt].vj = ej;
}
if(ans == -1) cout << "impossible" << endl;
else{
cout << ans << endl;
for(int i = cnt ; i >= 1 ; i --){
if(anss[i].vi == 1){
if(anss[i].vj == 1) cout << "FILL(1)" << endl;
if(anss[i].vj == 2) cout << "FILL(2)" << endl;
}
if(anss[i].vi == 2){
if(anss[i].vj == 1) cout << "POUR(1,2)" << endl;
if(anss[i].vj == 2) cout << "POUR(2,1)" << endl;
}
if(anss[i].vi == 3){
if(anss[i].vj == 1) cout << "DROP(1)" << endl;
if(anss[i].vj == 2) cout << "DROP(2)" << endl;
}
}
}
return 0;
}