POJ 3414 Pots

题目大意:

给三个杯子,容量分别为A,B,C,A,B,C得关系为1<=A,B<=100,C<=max(A,B);

可以对A,B杯子做以下三个操作:

  1. FILL(i)        fill the pot i (1 ≤ ≤ 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).

要求输出最小的操作次数使得A或者B杯子中液体的容量为C,并输出每次的具体操作。

解题思路:

这是一道宽搜问题,在宽搜的过程中要标记每次入栈的元素的步数,上一层入栈元素的下标以及该元素入栈时做的操作类型

将杯子A,B作为一个整体!

初态为(v1,v2)

进行操作DROP(1)标记为1

进行操作DROP(2)标记为2

进行操作FILL(1),标记为3

进行操作FILL(2)标记为4

进行操作POUR(1,2)标记为5

进行操作POUR(2,1)标记为6

代码如下:

#include<stdio.h>
#include<string.h>
int a,b,c;
int res,flag=0;
int head=0,tail=0;
char opr[6][10]={{"DROP(1)"},{"DROP(2)"},
{"FILL(1)"},{"FILL(2)"},{"POUR(1,2)"},{"POUR(2,1)"}};
struct Pot{         //每一个入队列的状态
    int v1;         //A杯子里液体的体积
    int v2;         //B杯子里液体的体积
    int type;       //入栈时所作的操作的类型
    int pre,step;   //上一层父节点在队列中的序号
};
Pot pot,pots[10010];
int mark[110][110];     //标记每一个状态(A,B杯子里的液体的体积),
void drop(int num){
    if(num==1){
        pot.v1=0;
        pot.v2=pots[head].v2;
        pot.pre=head;
        pot.type=1;
        pot.step=pots[head].step+1;
    }
    else if(num==2){
        pot.v1=pots[head].v1;
        pot.v2=0;
        pot.pre=head;
        pot.type=2;
        pot.step=pots[head].step+1;
    }
}
void fil(int num){
    if(num==1){
        pot.v1=a;
        pot.v2=pots[head].v2;
        pot.pre=head;
        pot.type=3;
        pot.step=pots[head].step+1;
    }
    else if(num==2){
        pot.v1=pots[head].v1;
        pot.v2=b;
        pot.pre=head;
        pot.type=4;
        pot.step=pots[head].step+1;
    }
}
void pour(int num1,int num2){
    if(num1==1 && num2==2){
        if(pots[head].v1+pots[head].v2<b){
            pot.v1=0;pot.v2=pots[head].v1+pots[head].v2;
            pot.pre=head;
            pot.type=5;
            pot.step=pots[head].step+1;
        }
        else{
            pot.v1=pots[head].v1+pots[head].v2-b;
            pot.v2=b;
            pot.pre=head;
            pot.type=5;
            pot.step=pots[head].step+1;
        }
    }
    else if(num1==2 && num2==1){
        if(pots[head].v1+pots[head].v2<a){
            pot.v1=pots[head].v1+pots[head].v2;
            pot.v2=0;
            pot.pre=head;
            pot.type=6;
            pot.step=pots[head].step+1;
        }
        else{
            pot.v1=a;
            pot.v2=pots[head].v1+pots[head].v2-a;
            pot.pre=head;
            pot.type=6;
            pot.step=pots[head].step+1;
        }
    }
}
void push(){
    pots[tail].v1=pot.v1;
    pots[tail].v2=pot.v2;
    pots[tail].type=pot.type;
    pots[tail].pre=pot.pre;
    pots[tail++].step=pot.step;
}
void bfs(){
    head=tail=0;
    pots[tail].v1=pots[tail].v2=0;
    pots[tail].type=0;
    pots[tail].pre=pots[tail++].step=0;
    while(head<tail){
        drop(1);
        if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        drop(2);
        if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        fil(1);
         if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        fil(2);
         if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        pour(1,2);
         if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        pour(2,1);
         if(mark[pot.v1][pot.v2]==0){
            mark[pot.v1][pot.v2]=1;
            push();
            if(pot.v1==c || pot.v2==c){
                break;
            }
        }
        head++;
    }
    if(head==tail){
        printf("impossible\n");
        flag=1;
    }
}
int main(){
    while(~scanf("%d%d%d",&a,&b,&c)){
        flag=0;
        memset(mark,0,sizeof(mark));
        bfs();
        if(flag)
            continue;
        tail--;
        printf("%d\n",pots[tail].step);
        int tmp=tail;
        int opera[1000],num=0;
        while(pots[tmp].type!=0){
            opera[num++]=pots[tmp].type;
            tmp=pots[tmp].pre;
        }
        for(int i=num-1;i>=0;i--){
            printf("%s\n",opr[opera[i]-1]);
        }
    }
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值