伫倚危楼风细细,望极春愁,黯黯生天际。草色烟光残照里,无言谁会凭阑意。

拟把疏狂图一醉,对酒当歌,强乐还无味。衣带渐宽终不悔,为伊消得人憔悴。——柳永

题目:倒水问题

网址:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=18&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.

Sample Input
2
2 3 4 2
96 97 199 62

Sample Output

2 2
9859 62

这道题可以使用优先队列BFS解决。

不难清楚,状态就是(a,b,c)代表三个容器中的当前水量(注意:顺序有差别)。

状态就是(a,b,c),直接跑一遍BFS即可。

核心在于,该状态记录起来过于繁琐,如何简化状态?

显然:总水量是定值,那么只要前两个容器水量确定,就可以刻画出了整个状态!所以状态数组仅需二维即可。该状态下需要判重。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std; const int maxn = 200 + 5;
struct node
{
int dist, cup[3];
bool operator < (const node& rhs) const
{
return dist > rhs.dist;
}
};
int cap[3], d, dis[maxn][maxn];
bool vis[maxn][maxn];
void bfs()
{
int ans = 0, num = 0x7f;
priority_queue <node> Q;
while(!Q.empty()) Q.pop();
if(cap[2] <= d)
{
printf("0 %d\n", cap[2]);
return;
}
memset(dis, 0x7f, sizeof(dis));
memset(vis, false, sizeof(vis));
node start;
start.dist = 0, start.cup[0] = 0, start.cup[1] = 0, start.cup[2] = cap[2];
Q.push(start);
dis[0][0] = 0;
vis[0][0] = true;
int v[3], count;
while(!Q.empty())
{
node now = Q.top(), next;
Q.pop();
v[0] = now.cup[0], v[1] = now.cup[1], v[2] = now.cup[2];
if(v[0] == d || v[1] == d || v[2] == d)
{
printf("%d %d\n", dis[now.cup[0]][now.cup[1]], d);
return;
}
for(int i = 0; i < 3; ++ i)
{
if(v[i] < d && ans < v[i])
{
ans = v[i];
num = now.dist;
}
if(v[i] == ans) num = min(num, now.dist);
} for(int i = 0; i < 3; ++ i)
{
if(now.cup[i])
for(int j = 0; j < 3; ++ j)
{
if(j != i)
{
if(now.cup[i] + now.cup[j] > cap[j]) count = cap[j] - now.cup[j];
else count = now.cup[i];
now.cup[i] -= count, now.cup[j] += count;
if(dis[now.cup[0]][now.cup[1]] - count >= dis[v[0]][v[1]])
{
dis[now.cup[0]][now.cup[1]] = dis[v[0]][v[1]] + count;
if(!vis[now.cup[0]][now.cup[1]])
{
vis[now.cup[0]][now.cup[1]] = true;
Q.push((node)
{
dis[now.cup[0]][now.cup[1]], now.cup[0], now.cup[1], now.cup[2]
});
}
}
now.cup[i] += count, now.cup[j] -= count;
}
}
}
}
printf("%d %d\n", num, ans);
return;
}
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
for(int i = 0; i < 3; ++ i)
scanf("%d", &cap[i]);
scanf("%d", &d);
bfs();
}
return 0;
}

该道题启示我们可以发掘一些隐含的条件来简化状态,从而简化时间及空间的复杂度。

UVA10603 倒水问题 Fill的更多相关文章

  1. uva10603 倒水问题

    状态搜索.类似八数码问题 AC代码 #include<cstdio> #include<queue> #include<cstring> #include<a ...

  2. UVa10603 倒水 Fill-状态空间搜索

    https://vjudge.net/problem/UVA-10603 There are three jugs with a volume of a, b and c liters. (a, b, ...

  3. 关于BFS和dijkstra(2019.04.20)

    我的BFS板子 struct node{/*略*/};//表示一个状态 std::map<node,bool>vis;//判断每个状态是否已访问过 std::queue<node&g ...

  4. UVa10603 Fill

    解题思路:这是神奇的一题,一定要好好体会.见代码: #include<cstdio> #include<cstring> #include<algorithm> # ...

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

    题目: Sample Input22 3 4 296 97 199 62Sample Output2 29859 62 题意: 有三个杯子它们的容量分别是a,b,c, 并且初始状态下第一个和第二个是空 ...

  6. 倒水问题(Fill, UVa 10603)

    [题目描述] 有三个没有刻度的水壶,容量分别为a,b和c(单位为升,都是<=200的正整数).初始时前两个水壶是空的,而第三个装满了水.每次可以从一个水壶往一个水壶里倒水,直到一个水壶倒空或者另 ...

  7. UVa 10603 Fill (BFS && 经典模拟倒水 && 隐式图)

    题意 : 有装满水的6升的杯子.空的3升杯子和1升杯子,3个杯子中都没有刻度.不使用道具情况下,是否可量出4升水呢? 你的任务是解决一般性的问题:设3个杯子的容量分别为a, b, c,最初只有第3个杯 ...

  8. 倒水问题(Fill,UVA 10603) lrj白书 p202

    看着lrj的代码自己敲了一遍,还没调试成功.... 有时间再进行完善 /* 状态start到各个状态u1,u2,u3..... 的倒水量分别为u1.dist,u2.dist,u3.dist.... * ...

  9. UVA-10603 Fill (BFS)

    题目大意:有三个已知体积但不知刻度的杯子,前两个杯子中初始时没有水,第三个装满水,问是否可以倒出d升水,如果倒不出,则倒出一个最大的d’,使得d’<=d,并且在这个过程中要求总倒水量最少. 题目 ...

随机推荐

  1. PTA | 1016 部分A+B (15分)

    正整数 A 的"DA(为 1 位整数)部分"定义为由 A 中所有 DA 组成的新整数 PA.例如:给定 A=3862767,DA=6,则 A 的"6 部分"PA ...

  2. PTA | 1008 数组元素循环右移问题 (20分)

    一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 ...

  3. Spring Boot入门系列(十)如何使用拦截器,一学就会!

    前面介绍了Spring Boot 如何整合定时任务已经Spring Boot 如何创建异步任务,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhon ...

  4. Scratch 全套学习资料

    链接:https://pan.baidu.com/s/1qX0T2B_zczcLaCCpiRrsnA提取码:xfp8

  5. Pytest系列(17)- pytest-xdist分布式测试的原理和流程

    pytest-xdist分布式测试的原理 前言 xdist的分布式类似于一主多从的结构,master机负责下发命令,控制slave机:slave机根据master机的命令执行特定测试任务 在xdist ...

  6. 03 GUI界面的错误日志查看及清除

    右上角图标,会显示当前使用工具的运行报错信息,点击可在下方查看到实际的错误日志

  7. https的秘钥公钥以及之间的会话流程

      一 共享秘钥 1.1 概念 共享秘钥和我们生活中同一把锁的钥匙概念类似,对同一把锁来说,加锁时使用什么钥匙,解锁也必须使用同样的钥匙. 1.2 共享秘钥在HTTP传输中的缺点 以共享密钥方式加密时 ...

  8. mount --bind绑定命令

    将目录或文件DirFile-1绑定到目录或文件DirFile-2上,所有对DirFile-2的访问就是对DirFile-1的访问 mount --bind [DirFile-1] [DirFile-2 ...

  9. 最长回文子窜O(N)

    字符窜同构的性质:同构字符窜拥有最小和最大的表示方法: 最长回文子窜: 1.首先暴力法:(n三方) 枚举每个起点和终点,然后单向扫描判断是不是回文子窜: 2.中心扩散法,(N方) 枚举每个中点,向外扩 ...

  10. Java成长第四集--文本处理IO流

    Java IO流在实际业务中使用的频率还是蛮高的,一些业务场景比如,文件的上传和导出,文件的读取等基本都是通过操作IO流来实现的,所以IO流是我们现在学习过程中必须要掌握的技能之一,熟练的使用IO流, ...