题目地址:POJ 3414
题意:给你a,b两个容器的容量,六种操作方法,问最少多少次可以使其中一个容器里的水达到体积c,如果不能的话则输出impossible。
思路:一共有6种操作方法,0:倒满a,1:倒满b,2:把a里的水倒向b(两种情况b倒满a有剩余或者a倒完),3:把b里的水倒向a(类似2的两种情况),4:把a倒空,5:把b倒空。然后用vis[i][j]记录当a的容量为i,b的容量为j时走了多少步,op[i][j][k]记录当a的容量为i,b的容量为j时用的第k步操作是谁。然后就是乱搞就好了。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef __int64 LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-7;
const int Maxn=110;
struct node {
int x,y;
} f1,f2;
int vis[Maxn][Maxn];
int op[Maxn][Maxn][Maxn];
int a,b,c;
void Operator(int i)
{
switch(i) {
case 0:
printf("FILL(1)\n");
break;
case 1:
printf("FILL(2)\n");
break;
case 2:
printf("POUR(1,2)\n");
break;
case 3:
printf("POUR(2,1)\n");
break;
case 4:
printf("DROP(1)\n");
break;
case 5:
printf("DROP(2)\n");
break;
}
}
void bfs()
{
int i,j;
queue<node >q;
memset(vis,-1,sizeof(vis));
vis[0][0]=0;
f1.x=0;
f1.y=0;
q.push(f1);
while(!q.empty()) {
f1=q.front();
q.pop();
if(f1.x==c||f1.y==c) {
printf("%d\n",vis[f1.x][f1.y]);
for(i=0; i<vis[f1.x][f1.y]; i++) {
Operator(op[f1.x][f1.y][i]);
}
return ;
}
for(i=0; i<6; i++) {
if(i==0) {
f2.x=a;
f2.y=f1.y;
}
if(i==1) {
f2.x=f1.x;
f2.y=b;
}
if(i==2) {
f2.y = f1.x + f1.y;
if(f2.y>=b) {
f2.x=f2.y-b;
f2.y=b;
} else
f2.x=0;
}
if(i==3) {
f2.x=f1.y+f1.x;
if(f2.x>=a) {
f2.y=f2.x-a;
f2.x=a;
} else
f2.y=0;
}
if(i==4) {
f2.x=0;
f2.y=f1.y;
}
if (i==5) {
f2.x=f1.x;
f2.y=0;
}
if(vis[f2.x][f2.y]==-1) {
vis[f2.x][f2.y]=vis[f1.x][f1.y]+1;
for(j=0; j<vis[f1.x][f1.y]; j++)
op[f2.x][f2.y][j]=op[f1.x][f1.y][j];
op[f2.x][f2.y][vis[f1.x][f1.y]]=i;
q.push(f2);
}
}
}
puts("impossible");
}
int main()
{
while(~scanf("%d%d%d",&a,&b,&c)) {
bfs();
}
return 0;
}