UVA 10603 Fill倒水问题

来源:互联网 发布:淘宝网帽子 编辑:程序博客网 时间:2024/06/05 19:02

There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater
than 200). The first and the second jug are initially empty, while the third is completely filled with
water. It is allowed to pour water from one jug into another until either the first one is empty or the
second one is full. This operation can be performed zero, one or more times.
You are to write a program that computes the least total amount of water that needs to be poured;
so that at least one of the jugs contains exactly d liters of water (d is a positive integer not greater
than 200). If it is not possible to measure d liters this way your program should find a smaller amount
of water d
′ < d which is closest to d and for which d

liters could be produced. When d

is found, your
program should compute the least total amount of poured water needed to produce d

liters in at least
one of the jugs.
Input
The first line of input contains the number of test cases. In the next T lines, T test cases follow. Each
test case is given in one line of input containing four space separated integers — a, b, c and d.
Output
The output consists of two integers separated by a single space. The first integer equals the least total
amount (the sum of all waters you pour from one jug to another) of poured water. The second integer
equals d, if d liters of water could be produced by such transformations, or equals the closest smaller
value d

that your program has found.
Sample Input
2
2 3 4 2
96 97 199 62
Sample Output
2 2
9859 62


题意:告诉三个杯子,总容量分别是a,b,c,最初只有C装满了,其他都为空,杯子没有刻度,只能互相倒水,问最终能否使得某个杯子有d单位的水,如果无法到达d,那就判断能到达的第一个小于d的单位能否到达,输出最小的倒水总量。

思路:把状态想想成结点,每次扩展取出水量最小的节点,然后各种转移。


#include <iostream>#include <stdio.h>#include <string>#include <cstring>#include <algorithm>#include <cmath>#include <queue>using namespace std;int cap[3];int vis[250][250];int ans[250];struct Node{    int v[3],dis;    bool operator < (const Node& rhs) const    {        return rhs.dis<dis;    }}f,t;void check(const Node& u){    for(int i=0;i<3;i++)    {        int a=u.v[i];        if(ans[a]<0 || u.dis<ans[a]) ans[a]=u.dis;    }}void solve(int a,int b,int c,int d){     cap[0]=a;cap[1]=b;cap[2]=c;    memset(ans,-1,sizeof ans);    memset(vis,0,sizeof vis);    priority_queue<Node>pq;    vis[0][0]=1;    f.dis=0;    f.v[0]=0; f.v[1]=0; f.v[2]=c;    pq.push(f);    while(!pq.empty())    {        f=pq.top();        pq.pop();        check(f);        if(ans[d]>=0) break;        for(int i=0;i<3;i++)            for(int j=0;j<3;j++)            {                if(i==j)continue;                if( f.v[i]==0 || f.v[j]==cap[j] ) continue;                int tmp=min(cap[j],f.v[i]+f.v[j])-f.v[j];                t=f;//只是对三个部分中的两个进行了操作,第三个 部分要直接赋值过去                t.dis=f.dis+tmp;                t.v[i]=f.v[i]-tmp;                t.v[j]=f.v[j]+tmp;                if(!vis[t.v[0]][t.v[1]])                {                    vis[t.v[0]][t.v[1]]=1;                    pq.push(t);                }            }    }        while(d>=0)            {                if(ans[d]>=0)                    {                        printf("%d %d\n",ans[d],d);                        return;                    }                d--;            }}int main(){    int a,b,c,d;    int T;   scanf("%d",&T);    {        while(T--)        {            scanf("%d%d%d%d",&a,&b,&c,&d);            solve(a,b,c,d);        }    }    return 0;}





0 0
原创粉丝点击