poj 3414 bfs 两个壶倒水,记录路径

题意:给你两个壶,容量分别为a,b,初始都是0,再给你一个目标水量c,问经过几次操作可以使得其中一个壶的水量为目标水量c,并且把操作步骤输出。

6个操作:

1、FILL(1)//FILL(i),把 i 壶装满

2、FILL(2)

3、DROP(1)//DROP(i),把 i 壶倒光

4、DROP(2)

5、POUR(1,2)//POUR(i,j)从 i 壶里倒水到 j 壶,直至 i 壶空了,或者 j 壶满了

6、POUR(2,1)


bfs最短路,关键点:

队列元素:两个壶的水量、在队列里的位置、上一个操作在队列里的位置、达到这个水量的操作(这三步是为了记录路径)


代码:


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int ms = 3e6;
struct node{
    int a,b;  
    int index;
    int way;
    int last;
};

node queue[ms];
int front,rear,visit[105][105] = {0},path[ms];

void Init(){
    front = rear = 0;
}

bool IsEmpty(){
    if(front == rear)
        return true;
    return false;
}

void Push(node x){
    if(visit[x.a][x.b])
        return;
    visit[x.a][x.b] = 1;
    x.index = rear;
    queue[rear++] = x;
    return;
}

void Pop(){
    front++;
    return;
}

void Print(int w){
    if(w == 1){
        printf("FILL(1)\n");
        return;
    }

    if(w == 2){
        printf("FILL(2)\n");
        return;
    }

    if(w == 3){
        printf("DROP(1)\n");
        return;
    }

    if(w == 4){
        printf("DROP(2)\n");
        return;
    }

    if(w == 5){
        printf("POUR(1,2)\n");
        return;
    }

    if(w == 6){
        printf("POUR(2,1)\n");
        return;
    }
    return;
}

int main(){
    int m1,m2,c,k;
    
    while(scanf("%d %d %d",&m1,&m2,&c) != EOF){
        k = -1;
        
        Init();
        node start;
        start.a = start.b = 0;
        start.index = 0;
        start.last = -1;
        start.way = -1;
        queue[0] = start;
        rear = 1;
        visit[0][0] = 1; 

        while(!IsEmpty()){
            node top = queue[front];
            Pop();
            if(top.a ==c || top.b ==c){
                int pos = top.index;
                
                while(queue[pos].way != -1){
                    path[++k] = queue[pos].way;
                    pos = queue[pos].last;
                }
                
                printf("%d\n",k+1);

                while(k >= 0){
                    Print(path[k]);
                    k--;
                }
                k = 0;
                break;
            }

            node newn;
            newn.last = top.index;
            //FILL(1) = 1;
            newn.a = m1;
            newn.b = top.b;
            newn.way = 1;
            Push(newn);

            //FILL(2) = 2;
            newn.a = top.a;
            newn.b = m2;
            newn.way = 2;
            Push(newn);

            //DROP(1) = 3;
            newn.a = 0;
            newn.b = top.b;
            newn.way = 3;
            Push(newn);

            //DROP(2) = 4;
            newn.a = top.a;
            newn.b = 0;
            newn.way = 4;
            Push(newn);

            //POUR(1,2) = 5;
            int tmp = m2 - top.b;
            if(tmp <= top.a){
                newn.a = top.a - tmp;
                newn.b = m2;
            }
            else{
                newn.a = 0;
                newn.b = top.b + top.a;
            }
            newn.way = 5;
            Push(newn);

            //POUR(2,1) = 6;
            tmp = m1 - top.a;
            if(tmp <= top.b){
                newn.a = m1;
                newn.b = top.b - tmp;
            }
            else{
                newn.a = top.a + top.b;
                newn.b = 0;
            }
            newn.way = 6;
            Push(newn);

        }

        if(k == -1)
            printf("impossible\n");

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值