Pots 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.
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
3 5 4
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int A,B,C;//输入数据,A,B为罐子容量,C为所要达到的值
struct pot{//罐子结构体
int a,b;//当前ab罐子中的量
int step;//次数
int pre;//它的父亲节点编号
int op;//变到当前状态的操作
}p,nextp,path[10000];
int vis[105][105];
void printPath(int x){
if(x==-1)return;//这就是为什么将第一个结构体的前驱设为-1,作为返回条件
printPath(path[x].pre);//回溯打印
switch(path[x].op){
case 0:
printf("FILL(1)\n");
break;
case 1:
printf("FILL(2)\n");
break;
case 2:
printf("DROP(1)\n");
break;
case 3:
printf("DROP(2)\n");
break;
case 4:
printf("POUR(1,2)\n");
break;
case 5:
printf("POUR(2,1)\n");
break;
}
return;
}
void Bfs(){
pot q[10000];//结构体数组模拟队列
int head = 0,tail = 0;
int i;
p.a = 0;
p.b = 0;
p.step = 0;
p.pre = -1;
p.op = -1;//初始化第一个点入队
vis[p.a][p.b] = 1;
q[tail++] = p;
path[head] = p;//路径保存下第零个顶点
while(head<tail){//六种操作 fill a,fill b,drop a,drop b,a->b,b->a
p = q[head];
if(p.a==C||p.b==C){
printf("%d\n",p.step);
printPath(head);//从当前这个标号开始向前寻找
return;
}
for(i = 0; i < 6; i++){
if(i==0){//fill a
nextp.a = A;
nextp.b = p.b;
nextp.step = p.step+1;
nextp.op = 0;//记录操作的编号
nextp.pre = head;//记录他的父亲状态节点编号
}
else if(i==1){//fill b
nextp.a = p.a;
nextp.b = B;
nextp.step = p.step+1;
nextp.op = 1;
nextp.pre = head;
}
else if(i==2){//drop a
nextp.a = 0;
nextp.b = p.b;
nextp.step = p.step+1;
nextp.op = 2;
nextp.pre = head;
}
else if(i==3){//drop b
nextp.a = p.a;
nextp.b = 0;
nextp.step = p.step+1;
nextp.op = 3;
nextp.pre = head;
}
else if(i==4){//a->b
if((B-p.b)>=p.a){//如果b中剩余空间大于a的量,a倒空
nextp.a = 0;
nextp.b = p.a+p.b;
}
else{//否则,b满,a剩余
nextp.a = p.a-(B-p.b);
nextp.b = B;
}
nextp.step = p.step+1;
nextp.op = 4;
nextp.pre = head;
}
else{//b->a
if((A-p.a)>=p.b){//如果a剩余空间大于b的量,b倒空
nextp.a = p.a+p.b;
nextp.b = 0;
}
else{//否则,a满b剩余
nextp.a = A;
nextp.b = p.b-(A-p.a);
}
nextp.step = p.step+1;
nextp.op = 5;
nextp.pre = head;
}
if(!vis[nextp.a][nextp.b]){
q[tail++] = nextp;
vis[nextp.a][nextp.b] = 1;
path[tail-1] = nextp;//每一个结构体在数组中的对应下标是固定了,所以可以利用这一性质记录父亲和儿子的下标关系就可以了
}
}
head++;
}
printf("impossible\n");
return;
}
int main(){
scanf("%d%d%d",&A,&B,&C);
memset(vis,0,sizeof(vis));
Bfs();
return 0;
}