UVA 10603_Fill

来源:互联网 发布:qq tim 知乎 编辑:程序博客网 时间:2024/06/03 03:30

题意:

给定三个杯子容量,初始只有第三个杯子满,其余为空,求最少需要倒多少水才能让某一杯子中有d升水,如果不能达到,则小于d且尽量接近。

分析:

因为要求转移水量最少,所以采用优先级队列保存每次的状态,保证每次都是取出转移水量最少的点进行扩展。bfs求出杯中水达到d(接近d)时最少转移水量。

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<queue>#include<cmath>using namespace std;const int maxn=205, INF=0x3fffffff;struct Node{    int n[3];    int dist;    bool operator < (const Node& a) const{        return dist > a.dist;    }};int vis[maxn][maxn], v[3], ans[maxn], d;void bfs(){    memset(vis, 0, sizeof(vis));    memset(ans, -1, sizeof(ans));    priority_queue<Node>q;    Node s;    s.n[0]=0, s.n[1] = 0, s.n[2] = v[2];    s.dist = 0;    vis[0][0]=1;    q.push(s);    while(!q.empty()){        Node t = q.top(); q.pop();        for(int i = 0; i < 3; i++){            if(ans[t.n[i]]<0) ans[t.n[i]] = t.dist;            else   ans[t.n[i]] = min(ans[t.n[i]], t.dist);        }        if(ans[d]>=0) break;        for(int i = 0; i < 3; i++){//i->j            for(int j = 0; j < 3; j++){                if(i!=j){                    if(t.n[i]==0||t.n[j]==v[j]) continue;                    int t1 = t.n[i], t2 = t.n[j];                    int temp = min(t1, v[j] - t2);                    Node nt;                    nt.n[i] = t1 - temp;                    nt.n[j] = t2 + temp;                    nt.n[3-i-j] = t.n[3-i-j];                    nt.dist = t.dist + temp;                    if(!vis[nt.n[0]][nt.n[1]]){//总水量一定,前两个杯子水量确定,第三个杯子水量也确定了                        vis[nt.n[0]][nt.n[1]] = 1;                        q.push(nt);                    }                }            }        }    }    while(ans[d]<0) d--;    printf("%d %d\n",ans[d], d);    return;}int main (void){    int T;scanf("%d",&T);    while(T--){        scanf("%d%d%d%d",&v[0],&v[1],&v[2],&d);        bfs();    }    return 0;}
0 0
原创粉丝点击