UVa10603 倒水 Fill-状态空间搜索

https://vjudge.net/problem/UVA-10603

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

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=201;
 7 struct Node{
 8     int x,y,z;
 9     int water;
10     bool operator<(const Node& b)const{
11         return water>b.water;
12     }
13 };
14 int a,b,c,d,ans[maxn],done[maxn][maxn];
15 void init(){
16     memset(ans,-1,sizeof(ans));
17     memset(done,0,sizeof(done));
18 }
19 int main()
20 {
21     int T;
22     scanf("%d",&T);
23     while(T--){
24         priority_queue<Node> Q;
25         init();
26         scanf("%d %d %d %d",&a,&b,&c,&d);
27         Node start=(Node){0,0,c,0};
28         Q.push(start);
29         while(!Q.empty()){
30             Node r=Q.top();Q.pop();
31             if(ans[r.x]<0||r.water<ans[r.x]) ans[r.x]=r.water;
32             if(ans[r.y]<0||r.water<ans[r.y]) ans[r.y]=r.water;
33             if(ans[r.z]<0||r.water<ans[r.z]) ans[r.z]=r.water;
34             done[r.x][r.y]=1;
35             if(ans[d]>=0) break;
36             int change;
37             change=min(r.x,b-r.y);
38             if(change&&!done[r.x-change][r.y+change]) Q.push((Node){r.x-change,r.y+change,r.z,r.water+change});
39             change=min(r.x,c-r.z);
40             if(change&&!done[r.x-change][r.y]) Q.push((Node){r.x-change,r.y,r.z+change,r.water+change});
41             change=min(r.y,a-r.x);
42             if(change&&!done[r.x+change][r.y-change]) Q.push((Node){r.x+change,r.y-change,r.z,r.water+change});
43             change=min(r.y,c-r.z);
44             if(change&&!done[r.x][r.y-change]) Q.push((Node){r.x,r.y-change,r.z+change,r.water+change});
45             change=min(r.z,a-r.x);
46             if(change&&!done[r.x+change][r.y]) Q.push((Node){r.x+change,r.y,r.z-change,r.water+change});
47             change=min(r.z,b-r.y);
48             if(change&&!done[r.x][r.y+change]) Q.push((Node){r.x,r.y+change,r.z-change,r.water+change});
49         }
50         while(d>=0){
51             if(ans[d]>=0){
52                 printf("%d %d\n",ans[d],d);
53                 break;
54             }
55             --d;
56         }
57     }
58     return 0;
59 }
时间: 2024-12-08 02:24:41

UVa10603 倒水 Fill-状态空间搜索的相关文章

UVa 11212 Editing a Book (IDA* &amp;&amp; 状态空间搜索)

题意:你有一篇n(2≤n≤9)个自然段组成的文章,希望将它们排列成1,2,-,n.可以用Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务.每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴.注意,剪贴板只有一个,所以不能连续剪切两次,只能剪切和粘贴交替.例如,为了将{2,4,1,5,3,6}变为升序,可以剪切1将其放到2前,然后剪切3将其放到4前.再如,排列{3,4,5,1,2},只需一次剪切和一次粘贴即可--将{3,4,5}放在{1,2}后,或者将{1,2}放在{3,4,5}前. 分析

UVa 1343 The Rotation Game (状态空间搜索 &amp;&amp; IDA*)

题意:有个#字型的棋盘,2行2列,一共24个格. 如图:每个格子是1或2或3,一共8个1,8个2,8个3. 有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面. 求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字.如果有多个解,输出字典序最小的操作步骤. 分析 : 还是状态空间的搜索,对象就是一个数字序列,判断中心位置是否一样,可以看出如果使用BFS,每一层还是爆炸,所以使用IDA*,关键还是模拟操作和h函数,这里的h函数是这样定义的,

状态空间搜索好题UVA10603

题目 分析:注意这里求的是最少流量, 二不是最少步数!!!所以我们用优先队列去维护一个最小流量,然后进行bfs即可,解释一下一个重要的数组ans[i],表示的是杯子中的水为i时的最小流量 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "queue" 5 #include "algorithm" 6 usin

【UVA10603】Fill (构图+最短路)

题目: Sample Input22 3 4 296 97 199 62Sample Output2 29859 62 题意: 有三个杯子它们的容量分别是a,b,c, 并且初始状态下第一个和第二个是空的, 第三个杯子是满水的.可以把一个杯子的水倒入另一个杯子,当然,当被倒的杯子满了或者倒的杯子水完了,就不能继续倒了. 你的任务是写一个程序计算出用最少的倒水量,使得其中一个杯子里有d升水.如果不能倒出d升水的话,那么找到一个d' < d ,使得d' 最接近d. 分析: 可以把每个状态即3个水杯里的

搜索专题总结

搜索专题总结 第七章的例题做得差不多了,还有一道枚举二叉树和一道比较难的搜方块的没过,另外有一道火柴的用IDA*水过,并没有过大数据,由于这道可以用dancing links过,所以留着dancing links一坑.接下来总结下这章的收获,首先最重要的当然是不需要判重的高效率的IDA*以及估价函数的设计技巧:然后是bfs+hash写得更熟练了,如果hash需要erase那么就只能用指针版的,但是效率会很慢,否则就用数组版的. 做搜索题的几个要点: 1,估算最坏复杂度. 2,寻找合适的剪枝策略,

UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: 3)采用广度优先搜索结点数越来越多,耗时过大: 经过简单计算,最长大概10次左右的变换就能出解,于是笔者就尝试采用IDA*,迭代加深搜索的好处是: 1)无需存储状态,节约时间和空间: 2)深度优先搜索查找的结点数少: 3)递归方便剪枝: 代码如下: 1 #include <iostream> 2

用BFS和DFS解决圆盘状态搜索问题

人工智能课程的实验(我的解法其实更像是算法课程的实验) 用到的算法:深度优先搜索.宽度优先搜索(状态扩展的不同策略) 数据结构:表示状态的结构体.多维数组 (可能是最近做算法竞赛题的影响,这次并不像以前那样依赖类和面向对象了,而是用最简单(几乎没有封装)的数据表示方法和大量的全局变量来存储数据,用面向过程的写法,以快速解决某一问题为目的设计程序.安全性和可扩展性势必降低,有些技巧的使用也让代码变得难懂:但是代码简洁,节省运行的时间和空间开销,这应该就是算法竞赛更加看重的吧) 这次用了C++写了控

NYOJ21 三个水杯 (经典问题 bfs)

题目描述: http://acm.nyist.net/JudgeOnline/problem.php?pid=21 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算.现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数. 输入 第一行一个整数N(0<N<50)表示N组测试数据 接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100

决策理论(Decision theory)&amp;自动规划和调度(Automated planning and scheduling)(双语)

译的不好,还请见谅... 大部分内容来自wiki decision theory决策理论部分: Normative and descriptive decision theory 规范和描述性决策理论 规范或规范的决策理论关心的是确定最好的决定(在实践中,有些情况下,"最好"的不一定是最大,最优可能还包括值除了最大,但在特定或近似范围),假设一个理想的决策者充分了解,能够准确无误地计算,完全理性的.这说明性的方法的实际应用(人们应该做出决定)决策分析,旨在发现工具,方法和软件帮助人们做