UVA-10603 Fill 倒水问题 BFS+优先队列

题目链接:https://vjudge.net/problem/UVA-10603

题意:设三个杯子的容量分别是a,b,c,最初只有第三个被子装满了c升水,其它两个杯子为空。最少需要倒多少升水才能让某一个杯子中的水有d升呢?如果无法做到恰好d升,就让某一个杯子里的水是d2升,其中d2<d,并且尽量接近d。(1<=a,b,c,d<=200).要求输出最少的倒水量和目标水量。

分析:本题的目标是倒的水量最少而不是步数最少。实际上,水量最少时步数不一定最少。例如:a=1,b=12,c=15,d=7,倒水量最少的方案是c->a,a->b重复7次。最后c里有7升水,一共14步,总水量也是14。还有一种方法c->b,然后b->a,a->c。重复4次,最后c里面7升水。一共10步,但总水量是20。这样的程序只需要把队列queue换成priority_queue,bfs搜索即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0x7fffffff;
const int MOD=1e9+7;
const int maxn=205;
int vis[maxn][maxn],cap[3],ans[maxn];
int a,b,c,d;

struct node{
    int v[3],dist;
    bool operator < (const node& rhs) const{
        return dist>rhs.dist;
    }
};

void init(){
    cap[0]=a;cap[1]=b,cap[2]=c;
    memset(vis,0,sizeof(vis));
    memset(ans,-1,sizeof(ans));
}

void update_ans(node &u){
    for(int i=0;i<3;i++){
        int d=u.v[i];
        if(ans[d]<0||u.dist<ans[d]) ans[d]=u.dist;
    }
}

void solve(){
    init();
    priority_queue<node> q;
    node start;
    start.dist=0;start.v[0]=0;start.v[1]=0;start.v[2]=c;
    q.push(start);
    vis[0][0]=1;
    while(!q.empty()){
        node u=q.top();q.pop();
        update_ans(u);
        if(ans[d]>=0) break;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i!=j){
                    if(!u.v[i]||u.v[j]==cap[j]) continue;
                    int amount=min(cap[j],u.v[i]+u.v[j])-u.v[j];
                    node u2;
                    memcpy(&u2,&u,sizeof(u));
                    u2.dist=u.dist+amount;
                    u2.v[i]-=amount;
                    u2.v[j]+=amount;
                    if(!vis[u2.v[0]][u2.v[1]]){
                        vis[u2.v[0]][u2.v[1]]=1;
                        q.push(u2);
                    }
                }
            }
        }
    }
    while(d>=0){
        if(ans[d]>=0){
            cout<<ans[d]<<' '<<d<<endl;
            return;
        }
        d--;
    }
}

int main() {
    //freopen("in.txt","r",stdin);
    int T;
    cin>>T;
    while(T--){
        cin>>a>>b>>c>>d;
        solve();
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值