码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 10603 Fill倒水问题

时间:2015-08-06 09:29:08      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

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 ?rst and the second jug are initially empty, while the third is completely ?lled with
water. It is allowed to pour water from one jug into another until either the ?rst 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 ?nd 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 ?rst 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 ?rst 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;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA 10603 Fill倒水问题

标签:

原文地址:http://blog.csdn.net/wust_zjx/article/details/47311167

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!