UVa 10603:Fill,经典倒水问题+隐式图搜索+dfs

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=110&page=show_problem&problem=1544

类型: 隐式图搜索

原题:

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.

样例输入:

2

2 3 4 2

96 97 199 62

样例输出:

2 2

9859 62

题目大意:

有三个杯子它们的容量分别是a,b,c, 并且初始状态下第一个和第二个是空的, 第三个杯子是满水的。可以把一个杯子的水倒入另一个杯子,当然,当被倒的杯子满了或者倒的杯子水完了,就不能继续倒了。

你的任务是写一个程序计算出用最少的倒水量,使得其中一个杯子里有d升水。如果不能倒出d升水的话,那么找到一个d' < d ,使得d' 最接近d。

分析与总结:

因为共有3个水杯, 根据每一杯的水量v1,v2,v3, 可以得到一个状态state(v1,v2,v3);

为了方便进行dfs搜索的状态转移,可以用两个三维数组volume[3], state[3]分别表示三个杯子的容量和状态。然后会有倒水的动作,可以从第1个杯子倒入第2,3个,从第2个倒入第1,3个等等……所以用两个for循环,可以遍历出所有的倒水方案。

然后注意一些不能倒水的条件,比如要倒的杯子是空的,目标杯子是满的,则不进行倒水的动作。

网上解题报告的方法: 用bfs做

// dfs,隐式图搜索
// URL:http://www.bianceng.cn/Programming/sjjg/201410/45697.htm
// Time: 0.072 s (UVA)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;  

int d, volume[3], state[3], minVolume, d1;
bool flag, vis[205][205][205];  

void search(int tot){
    // 更新结果的状态,有不少地方需要注意
    for(int i=0; i<3; ++i){
        if(state[i] && state[i] == d){
            d1 = d;
            if(!flag) minVolume = tot; // 第一次发现等于d,那么直接把当前总量tot赋给minVolume
            else if(tot<minVolume) minVolume = tot; // 以后有其他情况等于d的,只有tot小于minVolume才更新
            flag=true; // 标志为已经找到等于d的了
        }
        else if(!flag && state[i] && state[i] < d){// 注意: !flag表示只有没有找到等于d的情况,才会执行下面这些语句
            if(d-state[i]<d1){
                d1 = d-state[i];
                minVolume = tot;
            }
            else if(d-state[i]==d1 && tot<minVolume)
                minVolume = tot;
        }
    }  

    for(int i=0; i<3; ++i){
        for(int j=0; j<3; ++j)if(i!=j && state[i] && state[j]!=volume[j] ){   

            int add;
            int tmp_i = state[i], tmp_j = state[j]; // 备份,回溯后要恢复  

            if(state[i] >= volume[j]-state[j]){ // 如果倒的水大于等于被倒杯子剩余容量,那么将被倒满
                add = volume[j]-state[j];
                state[i] -= add;
                state[j] = volume[j];
            }
            else{ // 否则,全部倒光到目标杯子里
                state[j] += state[i];
                add = state[i];
                state[i] = 0;
            }  

            if(!vis[state[0]][state[1]][state[2]]){
                vis[state[0]][state[1]][state[2]] = true;
                search(tot+add);
                vis[state[0]][state[1]][state[2]] = false; // 回溯,恢复状态
            }  

            state[i] = tmp_i;    // 回溯,恢复状态
            state[j] = tmp_j;
        }
    }
}  

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d%d%d",&volume[0],&volume[1],&volume[2],&d);
        state[0]=0, state[1]=0, state[2]=volume[2];  

        memset(vis, 0, sizeof(vis));
        vis[0][0][volume[2]] = true;
        flag = false;
        minVolume = d1 = 1000000;
        search(0);  

        if(flag) printf("%d %d\n", minVolume, d1);
        else printf("%d %d\n", minVolume, d-d1);  

    }
    return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索状态
, 一个
, of
, The
One
隐式图搜索、dfs深度优先搜索、dfs深度优先搜索算法、dfs搜索、dfs搜索算法,以便于您获取更多的相关知识。

时间: 2024-08-19 21:00:48

UVa 10603:Fill,经典倒水问题+隐式图搜索+dfs的相关文章

uva 10603 - Fill bfs

10603 - Fill         经典的倒水问题,求最接近的可得到的水量d' d'<=d 和需要倒的水量       因为a,b,c最大只有200,所以总的状态只有8,000,000,而又因为总水量恒定,所以状态量只有40,000,bfs遍历即可.   /* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,please indicate the source** */ #i

uva 10603 - Fill

点击打开链接 题目所属:  隐式图的搜索 题目意思:  有三个容器大小为 a b  c 刚开始 a b都是空的 c是满的,现在给定一个d 大小的水量 ,要求我么找到最小的倒水总量使得有一个容器的水量为 d,如果找不到那么就用d'代替d(d' < d)直到能够找到有一个容器的水量为 d为止,最后输出 最小的倒水总量和 d' 解题思路:   倒水条件:假设是a倒入b中,那么必须要有a被倒空或 b 被倒满.                     经典的倒水问题,只是结果是要我们输出最小的倒水总量而不

无法将类型“System.Data.DataSet”隐式转换为“WebApplication1.DataSet2” 在线等,请各位高手帮忙

问题描述 namespaceWebApplication1{publicpartialclasshhhhhh:System.Web.UI.Page{///<summary>///sqlhelp的摘要说明///</summary>publicstaticclasssqlhelp{privatestaticstring_connstr="datasource=xzdb;uid=zc;pwd=zc;Unicode=True";publicstaticstringcon

第3课 隐式转换

1)val array=Array(1,2,3,4,5); array.map(item => 2*item);map的作用是循环遍历array中的每一个元素,并把每个元素做为具体的值传给map中的做为参数的函数.map执行结果为Array[Int] =Array(2,4,6,8,10);函数的参数也是函数,item时匿名函数,这个也是高阶函数 2)高阶函数的返回值也可能是函数.高阶函数的参数是函数,这是高阶函数的2个层面.高阶函数可以自动推断出函数参数的类型.而且对只有一个参数的函数,可以省略

小心MySQL的隐式类型转换陷阱

1. 隐式类型转换实例 今天生产库上突然出现MySQL线程数告警,IOPS很高,实例会话里面出现许多类似下面的sql:(修改了相关字段和值) SELECT f_col3_id,f_qq1_id FROM d_dbname.t_tb1 WHERE f_col1_id=1226391 and f_col2_id=1244378 and f_qq1_id in (12345,23456,34567,45678,56789,67890,78901,89012,90123,901231,901232,90

缺省构造函数不能处理隐式超构造函数抛出的异常类型 IOException。必须定义显式构造函数

问题描述 缺省构造函数不能处理隐式超构造函数抛出的异常类型 IOException.必须定义显式构造函数 int lastnum = getNum(source.getProperty(""fileName"")); public static int getNum(String Filename) throws IOException { InputStream myxls; myxls = new FileInputStream(Filename); sr =

JavaScript的隐式转换

JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object.object是引用类型,其它的五种是基本类型或者是原始类型.我们可以用typeof方法打印来某个是属于哪个类型的.不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换.隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等.. typeof '11'  //string       typeof(11) //number '11' < 4     /

C#教程:匿名类型和隐式类型变量的区别

隐式类型变量 (Implicitly typed local variables) 象下面的代码书写就是隐式类型变量 var i = 5; var str = "Csharp" var numbers = new int[]{1,2,3}; var orders = new System.Collections.Hashtable(); var orders1 = new Dictionary(); var i = xxx ; 的作用就是用 xxx 的类型声明为i的类型.并给i 赋值.

关于隐式挖掘网站用户行为的分析

隐式挖掘网站用户行为 如何了解用户和需求 如何了解用户需求?根据用户是否主动参与分为显式与隐式两种挖掘模式,因为显式的动静比较大,有很大局限性,所以为了保证结果准确性以及提高用户接受度,一般都采用隐式. 用户的日常交互行为会产生四类关键数据:鼠标移动轨迹.链接点击分布.页面浏览流.页面停留时间.通过用户的行为能反映用户的观点,同时利用访问的网页次序可以找出网页之间的隐性关系. 收集数据 Web服务器的日志(用户会话记录) Web trends或类似的第三方共享软件(客户端分析,流量分析,可用性分