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,并且在这个过程中要求总倒水量最少. 题目 ...
随机推荐
- java web利用mvc结构实现简单聊天室功能
简单聊天室采用各种内部对象不适用数据库实现. 一个聊天室要实现的基本功能是: 1.用户登录进入聊天室, 2.用户发言 3.用户可以看见别人发言 刚才算是简单的需求分析了,现在就应该是进 ...
- 微信网页授权,获取微信code,获取access_tocken,获取用户信息
微信开发中,经常有这样的需求:获得用户头像.绑定微信号给用户发信息.. 那么实现这些的前提就是授权! 1.配置安全回调域名: 在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 ...
- MySQl 和 Redis
MySQL MySQL 是关系型数据库,开放源码软件,主要使用持久化存储设备(像磁盘)数据存放在磁盘中,功能强大. 因为磁盘访问速度远远慢于内存,所以访问速度慢 Redis 是非关系型,高性能的key ...
- 2017蓝桥杯贪吃蛇(C++C组)
原题: 贪吃蛇长度+-------------------------------------------------+| ...
- scp 使用方法
scp就是secure copy,一个在linux下用来进行远程拷贝文件的命令.有时我们需要获得远程服务器上的某个文件,该服务器既没有配置ftp服务器,也没有做共享,无法通过常规途径获得文件时,只需要 ...
- WEB页面实现方法
页面分类 :添加页.修改页.列表页.详情页.功能页.删除 一.添加 1) 准备tpl.action(添加页.添加页保存公用一个action),并确认是否登录才显示2) 书写添加页action代码,例如 ...
- ubuntu 虚拟机复制后打开蓝屏解决办法
sudo apt-get install xserver-xorg-lts-utopic sudo dpkg-reconfigure xserver-xorg-lts-utopic reboot
- Pytest系列(20)- allure结合pytest,allure.step()、allure.attach的详细使用
如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 allure除了支持pyte ...
- java 中类为啥要序列化
java里为什么要序列化?http://zhidao.baidu.com/link?url=7_wAQ8eAl28vcJPE5OKM5Y0Bo4aINNQokHhRmI9XPszEoTO5QF-gNb ...
- Codeup 25609 Problem I 习题5-10 分数序列求和
题目描述 有如下分数序列 2/1,3/2,5/3,8/5,13/8,21/13 - 求出次数列的前20项之和. 请将结果的数据类型定义为double类型. 输入 无 输出 小数点后保留6位小数,末尾输 ...