poj 3414 Pots (bfs)

8 篇文章 0 订阅

链接:poj 3414

题意:给出了两个瓶子的容量A,B, 以及一个目标水量C,对A,B可以进行如下操作:

FILL(i)    将瓶i装满水

DROP(i)   将瓶i倒空

POUR(i,j) 将瓶i中的水倒入瓶j,此操作后要么瓶j装满水,要么瓶i为空

求至少要几次操作能使A或者B装的水为C,并输出具体操作

分析:可以从6个方面bfs,因为要输出具体操作,可以用数组模拟队列,

并记录前一次操作的状态,最后再回溯路径


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stu
{
    int step,a,b,pos;
}que[1010];
int a,b,c,ope[1010],step[1010],x,y,front,rear;
bool vis[105][105];
void fill(int i)
{
    if(i==1)
        x=a;
    else
        y=b;
}
void drop(int i)
{
    if(i==1)
        x=0;
    else
        y=0;
}
void pour(int i,int j)
{
    if(i==1){
        if(x+y>=b){
            x-=b-y;
            y=b;
        }
        else{
            y+=x;
            x=0;
        }
    }
    else{
        if(x+y>=a){
            y-=a-x;
            x=a;
        }
        else{
            x+=y;
            y=0;
        }
    }
}
void is_push(int step,int num)
{
    if(!vis[x][y]){
        que[rear].a=x;        
        que[rear].b=y;
        que[rear].step=step+1;  //记录步数
        que[rear].pos=front;   //记录前一次状态
        ope[rear++]=num;      //当前的操作
        vis[x][y]=true;   //标记为已访问
    }
}
int bfs()
{
    int i,num,q[7]={0,110,120,210,220,312,321};  //q数组用来标记执行的操作,以便最后输出
    struct stu t;
    front=0;
    rear=1;
    memset(vis,0,sizeof(vis));
    vis[0][0]=1;
    que[front].a=que[front].b=0;
    que[front].step=0;
    while(front<rear){
        t=que[front];
        if(t.a==c||t.b==c){
            num=t.step;
            step[num]=front;
            num--;
            while(num){
                step[num]=que[step[num+1]].pos;
                num--;
            }
            return t.step;
        }
        for(i=1;i<=6;i++){
            x=t.a;
            y=t.b;
            switch(i){
                case 1:fill(1);break;
                case 2:fill(2);break;
                case 3:drop(1);break;
                case 4:drop(2);break;
                case 5:pour(1,2);break;
                case 6:pour(2,1);
            }
            is_push(t.step,q[i]);
        }
        front++;
    }
    return -1;
}
int main()
{
    int sum,i,k;
    while(scanf("%d%d%d",&a,&b,&c)!=EOF){
        sum=bfs();
        if(sum==-1){
            printf("impossible\n");
            continue;
        }
        printf("%d\n",sum);
        for(i=1;i<=sum;i++){
            k=ope[step[i]];
            if(k/100==1)
                printf("FILL(%d)\n",k/10%10);
            else if(k/100==2)
                printf("DROP(%d)\n",k/10%10);
            else if(k/100==3)
                printf("POUR(%d,%d)\n",k/10%10,k%10);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值