UVA10603 倒水问题 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 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的更多相关文章
- uva10603 倒水问题
状态搜索.类似八数码问题 AC代码 #include<cstdio> #include<queue> #include<cstring> #include<a ...
- UVa10603 倒水 Fill-状态空间搜索
https://vjudge.net/problem/UVA-10603 There are three jugs with a volume of a, b and c liters. (a, b, ...
- 关于BFS和dijkstra(2019.04.20)
我的BFS板子 struct node{/*略*/};//表示一个状态 std::map<node,bool>vis;//判断每个状态是否已访问过 std::queue<node&g ...
- UVa10603 Fill
解题思路:这是神奇的一题,一定要好好体会.见代码: #include<cstdio> #include<cstring> #include<algorithm> # ...
- 【UVA10603】Fill (构图+最短路)
题目: Sample Input22 3 4 296 97 199 62Sample Output2 29859 62 题意: 有三个杯子它们的容量分别是a,b,c, 并且初始状态下第一个和第二个是空 ...
- 倒水问题(Fill, UVa 10603)
[题目描述] 有三个没有刻度的水壶,容量分别为a,b和c(单位为升,都是<=200的正整数).初始时前两个水壶是空的,而第三个装满了水.每次可以从一个水壶往一个水壶里倒水,直到一个水壶倒空或者另 ...
- UVa 10603 Fill (BFS && 经典模拟倒水 && 隐式图)
题意 : 有装满水的6升的杯子.空的3升杯子和1升杯子,3个杯子中都没有刻度.不使用道具情况下,是否可量出4升水呢? 你的任务是解决一般性的问题:设3个杯子的容量分别为a, b, c,最初只有第3个杯 ...
- 倒水问题(Fill,UVA 10603) lrj白书 p202
看着lrj的代码自己敲了一遍,还没调试成功.... 有时间再进行完善 /* 状态start到各个状态u1,u2,u3..... 的倒水量分别为u1.dist,u2.dist,u3.dist.... * ...
- UVA-10603 Fill (BFS)
题目大意:有三个已知体积但不知刻度的杯子,前两个杯子中初始时没有水,第三个装满水,问是否可以倒出d升水,如果倒不出,则倒出一个最大的d’,使得d’<=d,并且在这个过程中要求总倒水量最少. 题目 ...
随机推荐
- A. Remainder Codeforces Round #560 (Div. 3)
A. Remainder Codeforces Round #560 (Div. 3) You are given a huge decimal number consisting of nn dig ...
- 关于 Vue 中 我对中央事线管理器的(enentBus)误解
由于这段时间公司比较闲,就对vue 中的一些模糊的点做了一些加强,突然就想到了常挂在嘴边兄弟组件传值 我理解的兄弟组件的传值是可以跨理由传值的,比如我从http://localhost:8080/lo ...
- 解决VS项目程序运行完就自动关闭窗口
VS的程序运行完会关闭窗口,需要设置工程属性 笔者虽然是Java开发者,但是学习用到了C++与C语言,之前使用的是dev与codeblock并没有这个情况,那么如何解决 首先你有这个hello,wor ...
- Linux基础:Day03
Linux的网络 以太网的发明--PC之间文件共享情况出现 网卡硬件设备 -- MAC地址 一层:物理层 HUB -- 集线器 总线型结构 泛洪 广播域/冲突域 二层: 在早期的网络中,PC互通 ...
- Jmeter 压力测试笔记(1)--服务器迁移失败
近期,公司服务器因技术架构升级等原因需要迁移,在经过开发,运维DBA,测试多部门进行联合讨论后,制定出了迁移方案.迁移前也对APP应用进行了各种测试,并没有发现问题. 凌晨2点开始迁移,5点完成迁移. ...
- C语言把浮点数转换为字符串
目录 1.把float/double格式化输出到字符串 2.注意事项 3.版权声明 1.把float/double格式化输出到字符串 标准的C语言提供了atof函数把字符串转double,但是没有提供 ...
- SpringMVC(一):简介和第一个程序
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...
- JS 浏览器BOM-->简介和属性
1.简介: BOM:浏览器对象模型(Browser Object Model),是一个用于访问浏览器和计算机屏幕的对象集合.我们可以通过全局对象window来访问这些对象. 2.属性 window. ...
- xftp连接centos7
1.下载xftp文件,并正常进行安装 2.安装好之后运行,并新建会话,此时可见如下界面: 注意: 名称,可随便输入,自己能看懂是什么就行 主机,输入当前Linux服务器的ip(如何获取服务器 ...
- AD颗粒化密码规则策略
我们在第一次设定密码规则的时候,通常会在根节点或者默认组策略中设置 如果,我们在后期运维过程中,有一些特殊用户需要设置额外的密码策略,我们要如何操作呢? 可能,有些同学会在这些特殊用户对应的OU下在创 ...