POJ 3414 Pot (输出路径)【BFS】

<题目链接>

题目大意:

有两个容量的空杯子,能够对这两个空杯子进行三种操作:

分别是fill(a),装满a杯子;

drop(a),倒空a杯子;

pour(a,b),将a杯子中的水倒入b杯子中;

现在问你,是否能够通过这三种操作,使得这两个杯子中至少有一个杯子中含有c体积的水,如果不行,输出“impossible”,如果可以,输出操作的步数,以及每一步的具体操作。

解题分析:

此题与一道输出路径的很相像,只不过那道题是输出每一次操作对应的点的状态,而此题是要输出具体的操作。不难想到,我们依然可以记录下BFS路径上点的状态,然后根据这个点和上一个点的状态差距推导出它们之间的具体操作。

#include <cstdio>
#include <cstring>

int v[5],m;

const int maxn=100000;
int vis[110][110];
int flag;

struct node{
    int val[5];
    int step;
    int pre;     //记录上一个点在que[]数组中的位置
    node(int a=0,int b=0,int c=0,int d=-1){
        val[1]=a,val[2]=b,step=c,pre=d;
    }
}que[maxn];

 void fill(node &now,int a){
    now.val[a]=v[a];
}

void drop(node &now,int a){
    now.val[a]=0;
}

void pour(node &now,int a,int b){
    int sum=now.val[a]+now.val[b];
    if(sum>v[b]){
        now.val[b]=v[b];
        now.val[a]=sum-v[b];
    }
    else{
        now.val[b]=sum;
        now.val[a]=0;
    }
}

void print(node tmp){         //根据相邻两个点的状况来推断操作
    if(tmp.pre!=-1){
        print(que[tmp.pre]);
    }
    if(tmp.pre!=-1){       //如果这个点和上一个点之间有操作,就可以将这个操作求出来
        node prenode=que[tmp.pre];
        node cal=prenode;
        pour(cal,1,2);
        if(tmp.val[1]==v[1]&&tmp.val[2]==prenode.val[2]){
            printf("FILL(1)\n");
        }
        else if(tmp.val[2]==v[2]&&tmp.val[1]==prenode.val[1]){
            printf("FILL(2)\n");
        }
        else if(tmp.val[1]==0&&tmp.val[2]==prenode.val[2]){
            printf("DROP(1)\n");
        }
        else if(tmp.val[2]==0&&tmp.val[1]==prenode.val[1]){
            printf("DROP(2)\n");
        }
        else if(cal.val[1]==tmp.val[1]&&cal.val[2]==tmp.val[2]){
            printf("POUR(1,2)\n");
        }
        else{
            printf("POUR(2,1)\n");
        }
    }
}

void bfs(){
    memset(vis,0,sizeof(vis));
    int front=0,end=0;
    vis[0][0]=1;
    que[end++]=node(0,0,0,-1);
    while(front<end){
        node now=que[front];
        front++;
        if(now.val[1]==m||now.val[2]==m){
            flag=true;
            printf("%d\n",now.step);
            print(now);
            return;
        }
        for(int i=1;i<=2;i++){        //装满
            node tmp=now;  //注意,这里为了防止now发生改变,从而对后面的操作产生影响,所以这里是对tmp进行操作
            fill(tmp,i);
            if(!vis[tmp.val[1]][tmp.val[2]]){
                vis[tmp.val[1]][tmp.val[2]]=1;
                que[end++]=node(tmp.val[1],tmp.val[2],tmp.step+1,front-1);
            }
        }
        for(int i=1;i<=2;i++){        //倒空
            node tmp=now;
            drop(tmp,i);
            if(!vis[tmp.val[1]][tmp.val[2]]){
                vis[tmp.val[1]][tmp.val[2]]=1;
                que[end++]=node(tmp.val[1],tmp.val[2],tmp.step+1,front-1);
            }
        }
        for(int i=1;i<=2;i++){       //i向j注水
            for(int j=1;j<=2;j++){
                if(i==j)continue;
                node tmp=now;
                pour(tmp,i,j);
                if(!vis[tmp.val[1]][tmp.val[2]]){
                    vis[tmp.val[1]][tmp.val[2]]=1;
                    que[end++]=node(tmp.val[1],tmp.val[2],tmp.step+1,front-1);
                }
            }
        }
    }
}

int main(){
    while(scanf("%d %d %d",&v[1],&v[2],&m)!=EOF){
        flag=false;
        bfs();
        if(!flag){
            printf("impossible\n");
        }
    }
    return 0;
}

2018-08-29

原文地址:https://www.cnblogs.com/00isok/p/9557340.html

时间: 2024-12-09 18:54:52

POJ 3414 Pot (输出路径)【BFS】的相关文章

Pots POJ - 3414【状态转移bfs+回溯】

典型的倒水问题: 即把两个水杯的每种状态视为bfs图中的点,如果两种状态可以转化,即可认为二者之间可以连一条边. 有3种倒水的方法,对应2个杯子,共有6种可能的状态转移方式.即相当于图中想走的方法有6种,依次枚举即可. 用一个二维数组标记状态,以免重复. 难点在于输出路径,即bfs回溯. 我的处理方法是,在bfs的队列基础上,用一个vector保存每一个可能的状态,即每个状态对应一个编号.同时结构体中不仅保存每个状态的信息,而且还要保存每个状态的对应编号和上一个状态的对应编号. 那么,当bfs到

POJ 3414 Pots 记录路径的广搜

Description 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

广搜+输出路径 POJ 3414 Pots

POJ 3414 Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13547   Accepted: 5718   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)

POJ 3414 Pots (BFS + 记录路径)

Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10300 Accepted: 4362 Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        fill th

(poj)3414 Pots (输出路径的广搜)

Description 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

Pots--poj(bfs,输出路径)

http://poj.org/problem?id=3414 题意: 给你两个容量为a,b的杯子:有3个操作: 1:FILL(i):把第i个杯子从水库中装满: 2:DROP(i):把第i个杯子清空: 3:POUR(i,j):把第i个杯子的水移入到j中,直到第i个杯子空了或者第j个杯子满了为止: 分析:本题和上篇的差不多,多的就是输出路径: 包含六个过程:水池—>a: 水池—>b:a->水池:b->水池:a->b:b->a: |  prea pre[x][y] |  pr

POJ 3414 Pots (经典bfs )

Description 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

poj 3414 Pots (bfs+线索)

Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10071   Accepted: 4237   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        f

Pots POJ - 3414 (搜索+记录路径)

Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22688   Accepted: 9626   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        f