POJ3414-Pots

题面

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; 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).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

题意

给出了两个瓶子的容量A,B, 以及一个目标水量C,对A,B做3种操作,使某一个瓶子的水量为C,求最小操作数,并输出具体操作

分析

注意题中A,B都在100以内,且状态深度较大,故考虑bfs+记忆化。
本题思想简单,到这里就差不多了。
但代码有有点麻烦,需要输出具体方案。
可以考虑每个状态都记录下它从什么状态转移过来。
具体实现还需要注意一些代码技巧,网上有些人这题博客写到两百多行,其实大可不必,可以看一看我代码的实现。

代码

//2152:Pots
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=100+10;
int A,B,C,top,sz;
bool vis[maxn][maxn];
char c[6][9]={{'D','R','O','P','(','1',')'},{'D','R','O','P','(','2',')'},
             {'F','I','L','L','(','1',')'},{'F','I','L','L','(','2',')'},
             {'P','O','U','R','(','1',',','2',')'},{'P','O','U','R','(','2',',','1',')'}};
struct node{
    int a,b,id,k,step,last;
}f[100000],stk[100000],ans;
queue<node> q;
void pour(int& u,int &v,int cap){
    if(u+v>=cap) u=u+v-cap,v=cap;
    else v=u+v,u=0;
}
void bfs(){
    node x;
    while(!q.empty()){
        x=q.front();q.pop();
        vis[x.a][x.b]=true;
        if(x.a==C||x.b==C){
            ans=x;break;
        }
        node to;
        to=x;to.a=0;to.step++;to.last=x.id;to.k=1;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
        to=x;to.b=0;to.step++;to.last=x.id;to.k=2;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
        to=x;to.a=A;to.step++;to.last=x.id;to.k=3;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
        to=x;to.b=B;to.step++;to.last=x.id;to.k=4;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
        to=x;pour(to.a,to.b,B);to.step++;to.last=x.id;to.k=5;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
        to=x;pour(to.b,to.a,A);to.step++;to.last=x.id;to.k=6;to.id=++top;f[top]=to;
        if(!vis[to.a][to.b]) q.push(to);
    }
}
int main()
{
    cin>>A>>B>>C;
    if(!C) {printf("0");return 0;}
    node x;x.a=0;x.b=0;x.id=1;x.step=0;x.last=-1;f[++top]=x;
    q.push(x);bfs();
    if(ans.step) printf("%d\n",ans.step);
    else {printf("impossible");return 0;}
    while(ans.last!=-1) stk[++sz]=ans,ans=f[ans.last];
    int hwq;
    for(int i=sz;i;i--){
        if(stk[i].k==5||stk[i].k==6) hwq=9;else hwq=7;
        for(int j=0;j<hwq;j++)
            printf("%c",c[stk[i].k-1][j]);
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值