UVA 10603 Fill倒水问题

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;
}

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

时间: 2024-10-14 20:42:30

UVA 10603 Fill倒水问题的相关文章

uva 10603 Fill (BFS)

uva 10603 Fill 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

UVA 10603 Fill(正确代码虽然很搓,网上许多代码都不能AC)

在做用户查找时 因为要把查找的结果动态加载和显示,所以,那些html元素要由Ajax动态生成.用户打开查找界面时,有系统推荐的用户,而当用户按条件查找后,查找的结果动态加载和显示.所以考虑到用js来搞. 这个for循环就是移除已有的表单.然后根据Ajax请求过来的数据,动态生成新的表单对象.一定要注意j变量从大往小循环,否则,删除div元素后会引起serchResultLenth=serchResult.children.length;长度的变化(这个问题摸索了好久,才搞定,切记) for(va

UVa 10603 Fill [暴力枚举、路径搜索]

10603 Fill 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 f

Fill (Uva 10603 bfs 倒水问题)

题意:三个杯子容量分别为a,b,c,现在c是满的,a和b是空的,两个杯子 i 向 j 倒水,要么 i 倒完了 j 还没满,要么 j 满了 i 还有剩余,问达到某个杯子水量为d时总共倒得最小水量是多少?如果不能达到d,找一个小于d并且离d最近的一个解. 思路:倒水问题,但题目要求的是总的到水量,所以在bfs时到达过的状态还要检查更新,可能当前我确实到达d了用了sum水量,但可能后面还有比sum更小的解.网上有很多代码都是错误的,很多就是错在这里. 代码: #include <iostream>

uva 10603 Fill(倒水问题 BFS)

貌似uva崩了,现在进不去,所以这道题还判断正确与否,其实无所谓了,我这是看的网上的代码,写的基本上一样,唉,没办法,不会做,又看了网上的题解,认真写理解吧还是... 构造了一个结构体,water数组用来保存三个杯子的状态,sum用来保存当前的倒水量,visit数组用来保存状态,以 防他们重复访问,三个杯子只需要两个杯子来判断,第三个已经确定,所以开一个二维数组就可以了...然后用 reach数组来存储所有的倒水量,下标是目标水量,值是一共的倒水量... 只需要一次BFS最多有200*200种状

UVA 10603 Fill(正确代码尽管非常搓,网上很多代码都不能AC)

题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=1544">click here~ 此题我预计是加强过数据,在我纠结了非常久的时候我交了好几份网上的代码不是WA就是TLE.在我非常迷茫的时候我又交了一份,AC了(尽管我用随机数据找到了他代码一个不能过的数据). 给了我信心.然后我拿他的代码用随机数跟我的代码进行測试.再用FC找不同..发现了一个致命的错误.一般来说,BFS或者DFS都是须要

UVa 10603 Fill (暴力BFS+优先队列)

题意:给定4个数,a,b,c,d,分别代表空杯子容积为a,b,一个盛满水的杯子容积为c,让你不断倒水,找一个dd,是不是存在某个时刻, 某个杯子里的水dd,和d相同,或者无限接近.让求最少的倒水量和dd(可能和d相同). 析:首先由于没有刻度,如果用数学方法计算,不好算,样例还好算一点,我们观察那个a,b,c都不大于200,挺小的,适合暴力求解. 就是把所有情况都倒一次,倒水就两种倒法,要么把一个杯子倒满,要么就是这个杯子空了,由于水量是固定的,那么确定两个杯子的水量, 那么第三个也就确定了,所

UVA - 10603 Fill(隐式图搜索)

题目大意:经典的倒水问题.给你三个瓶子,体积为a,b,c. 刚开始a,b是空的,c是满的,现在要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多少,如果不能倒出体积为d的水,找出d' < d,最接近d的d'和最小的体积 解题思路:刚才时以为直接bfs,用vis标记一下就结束了,结果WA了.为什么会WA,因为我这样求的是倒水次数最少的,而不是倒水体积最小的,WA是肯定的了 接着将vis数组改成int型的,纪录达到这个状态时倒水的体积,结果可想而

【路径寻找问题】UVa 10603 - Fill

如家大神书上的例题.第一次接触也是按代码敲得.敲的过程感觉很直观.但自己写估计会写的乱七八糟.以后不能砍得难就不愿意做这种题.否则只能做一些水题了.(PS:48) 紫书 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int maxn =