UVA - 10603 Fill(bfs+优先队列+动态规划)
来源:互联网 发布:linux获得root权限 编辑:程序博客网 时间:2024/06/15 13:53
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
Sample Output
2
2 3 4 2
96 97 199 62
2 2
9859 62
题目大意:设3个杯子的容量分别为a,b,c,最初只有第3个杯子装满了c升水,其他两个杯子为空。最少需要倒多少升水才能让某一个杯子中的水有d升呢?
如果无法做到恰好为d升,就让某个杯子的水尽量接近d。
解析:UVA上面的数据可能改了,我看了网络上面的其他代码很多都是TLE,所以这题如果用单纯的bfs来做肯定会超时,所以我这里用到了动态规划的思想,用一个ans数组,来保存每升水,最少用多少总水量才能到达,并用优先队列进行优化。
即每次取出最少的用水量的节点,将最少用水量的节点中的每杯水的用水量,保存在ans数组中,并且一直更新。最后输出 d ~ 0中,第一个用水量不为-1的ans的值。
AC代码:
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;struct Node {int v[3],dist;bool operator < (const Node& rhs) const {return this->dist > rhs.dist; //从小到大排列}};const int MAX = 200 + 5;int vis[MAX][MAX],jug[3],ans[MAX];int d;void update(const Node& u) {for(int i = 0; i < 3; i++) {int t = u.v[i];if(ans[t] < 0 || u.dist < ans[t]) { //求到达t状态,所用的最少水量ans[t] = u.dist;}}}void bfs() {memset(vis,0,sizeof(vis));memset(ans,-1,sizeof(ans));priority_queue<Node> q; //构造优先队列Node start;start.dist = 0;start.v[0] = 0;start.v[1] = 0;start.v[2] = jug[2];q.push(start);vis[0][0] = 1; //初始化viswhile(!q.empty()) {Node u = q.top();q.pop();update(u);if(ans[d] >= 0) { //如果目标的用水两 >= 0,则退出break;}for(int i = 0; i < 3; i++) {for(int j = 0; j < 3; j++) {if(i == j) { //两杯水不能相等continue;}if(!u.v[i] || u.v[j] == jug[j]) { //i没有水,或者j已经满了,跳过continue;}int amount = min(u.v[i],jug[j]-u.v[j]);Node u2 = u;u2.dist += amount;u2.v[i] -= amount;u2.v[j] += amount;if(!vis[u2.v[0]][u2.v[1]]) {vis[u2.v[0]][u2.v[1]] = true;q.push(u2);}}}}}int main() {int t;while(scanf("%d",&t) != EOF) {while(t--) {scanf("%d%d%d%d",&jug[0],&jug[1],&jug[2],&d);bfs();while(d >= 0) {if(ans[d] >= 0) {printf("%d %d\n",ans[d],d);break;}d--;}}}return 0;}
- UVA - 10603 Fill(bfs+优先队列+动态规划)
- UVA-10603-Fill(BFS+优先队列)
- UVA FILL(BFS + 优先队列)
- UVA-10603 Fill 倒水问题 BFS+优先队列
- UVA10603 FILL 优先队列+BFS
- uva 10603 Fill (BFS)
- UVa 10603:Fill(BFS)
- UVa 10603 BFS+优先队列
- uva 10603 - Fill bfs
- UVA 10603 - Fill BFS~
- UVA 10603 Fill【BFS】
- uva 10603 Fill(倒水问题 BFS)
- Fill (Uva 10603 bfs 倒水问题)
- Uva10603 Fill 【隐式图bfs(优先队列)】【例题7-8】
- uva 11573 - Ocean Currents(bfs+优先队列)
- UVa 10603 Fill( BFS + 判重)
- FILL uva+bfs
- UVa 10047 - The Monocycle, 优先队列+BFS
- 位排序
- 二天个人提供乳房和天赋规划图
- 最近需要看的几本书
- [资源推荐] 开源工具链博客
- LeetCode --- Binary Tree Preorder Traversal
- UVA - 10603 Fill(bfs+优先队列+动态规划)
- 黑马程序员—(iOS开发)C语言简单编程---(二)
- 二条特让他让他一人一天有图有
- 不重复随机数列生成算法
- 【Java集合源码剖析】LinkedList源码剖析
- 多线程
- 数据结构学习笔记(三)---求1+2+3+...+100的和
- ZOJ 2588 Burning Bridges(判断割边)
- Cocos2d-x 动手实现游戏主循环