Pots POJ - 3414(BFS+路径还原)







 Pots POJ - 3414

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

  1. FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap;
  2. DROP(i)      empty the pot i to the drain;
  3. 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.

Input

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).

Output

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’.

Sample Input
3 5 4
Sample Output
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
思路:Bfs的思路很容易想到,就是路径还原的时候,用数组模拟队列比较方便,因为这样每个结构体都对应一个确定的下标,这样每个节点的标号就知道了,就可以用标号来
存父亲,最后回溯打印即可
代码:
#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值