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

混江龙づ霸主 提交于 2020-02-13 14:20:04

<题目链接>

题目大意:

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

分别是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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!