题目:

给出三个杯子(没有刻度线)的容量,起初之后第三个杯子是满的,其他的两个杯子是空的,容量分别是a、b、c。问最少需要倒多少升水才能让某一个杯子中的水有d升?如果不能恰好做到d升,就让某一个杯子里的水是D升,其中D<d并且尽量接近d。(1≤a,b,c,d≤200)。要求输出最少的倒水量和目标水量d或D。

思路:

菜是原罪,需要赎罪啊!!

1.一看到这种求最小值的问题很应该想到是用BFS了。

2.BFS需要标记状态呀,那201*201*201=8120601这内存有些吃不消啊,那前两个杯子的水固定了,总的水量又是不变的,那只用前两个杯子的

水量就可以标记所有可能的状态了。这样就把状态缩小到201*201了。

3.Node结构体中保存的是一个状态,“状态”这个词很玄乎啊,有到当前状态已经倒过的水量dist和三个杯子中还有的水量v[0]、v[1]、v[2]。

4.紫书的代码写的优美啊!!值的好好的学习!!

代码:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define MAX 1000000009
#define FRE() freopen("in.txt","r",stdin)
#define FRO() freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
const int maxn = ;
struct Node{
int v[],dist;//dist保存的是到当前状态已经倒过的最小水量
bool operator<(const Node& rhs)const{
return dist>rhs.dist;
}
};
int vis[maxn][maxn],cap[],ans[maxn]; void update_ans(const Node& u){//更新答案
for(int i=; i<; i++){
int d=u.v[i];
if(ans[d]< || u.dist<ans[d])
ans[d] = u.dist;
}
} void solve(int a,int b,int c,int d){
cap[]=a;cap[]=b;cap[]=c;//记录目标状态的水量是多少
memset(vis,,sizeof(vis));//清空所有的可能出现的状态
memset(ans,-,sizeof(ans));//清空答案数组
priority_queue<Node>q; Node start;//初始状态,按照题目要求赋值
start.dist = ;
start.v[] = start.v[] = ;
start.v[] = c;
q.push(start);
vis[][] = ;//标记a、b杯子为空的状态
while(!q.empty()){
Node u = q.top();q.pop();
update_ans(u);
if(ans[d]>=) break;//如果已经找到的答案就break
for(int i=; i<; i++){//i表示的是倒出水的杯子
for(int j=; j<; j++){//j表示的是被倒出水的杯子
if(i!=j){//自己不能给自己倒水
if(u.v[i]== || u.v[j]==cap[j])continue;//如果倒出水的杯子里没有水
//被倒的杯子已经满了,就进行下一个状态
int amount = min(cap[j], u.v[i]+u.v[j])-u.v[j];//重点了!!
/*
要倒一定是全部倒出来,所以j杯子被倒水之后有两种状态
1.倒之后满了
2.倒之后没有满
从这两种状态中取一个最小的水量记录下来
*/
Node u2;//赋值一个新的状态
memcpy(&u2, &u, sizeof(u));
u2.dist = u.dist+amount;
u2.v[i] -= amount;
u2.v[j] += amount;
if(!vis[u2.v[]][u2.v[]]){//如果这个状态没有出现过,就标记一下入队列
vis[u2.v[]][u2.v[]] = ;
q.push(u2);
}
}
}
}
}
while(d>=){//遍历答案并输出
if(ans[d] >= ){
printf("%d %d\n",ans[d],d);
return;
}
d--;
}
} int main(){
int T,a,b,c,d;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&a,&b,&c,&d);
solve(a,b,c,d);
}
return ;
}

UVA - 10603 Fill(BFS求最小值问题)的更多相关文章

  1. UVA 10603 - Fill BFS~

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&c ...

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

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

  3. UVa 10603 Fill [暴力枚举、路径搜索]

    10603 Fill There are three jugs with a volume of a, b and c liters. (a, b, and c are positive intege ...

  4. UVa 10603 Fill (暴力BFS+优先队列)

    题意:给定4个数,a,b,c,d,分别代表空杯子容积为a,b,一个盛满水的杯子容积为c,让你不断倒水,找一个dd,是不是存在某个时刻, 某个杯子里的水dd,和d相同,或者无限接近.让求最少的倒水量和d ...

  5. UVA 10603 Fill(正确代码尽管非常搓,网上很多代码都不能AC)

    题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=1544">click here~ ...

  6. UVA - 10603 Fill(隐式图搜索)

    题目大意:经典的倒水问题. 给你三个瓶子,体积为a,b,c. 刚開始a.b是空的,c是满的,如今要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多 ...

  7. UVA 10603 Fill

    题意: 题目的意思是倒水,给出的四个数据是第一个水杯,第二个水杯,第三个水杯,和目标水量.一开始只有第三个水杯是满的,剩下的水杯是空的.倒水的时候只能把倒水出来的这个杯子倒空,或是倒水进去的杯子倒满. ...

  8. 【路径寻找问题】UVa 10603 - Fill

    如家大神书上的例题.第一次接触也是按代码敲得.敲的过程感觉很直观.但自己写估计会写的乱七八糟.以后不能砍得难就不愿意做这种题.否则只能做一些水题了.(PS:48) 紫书 #include<ios ...

  9. 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。

    这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...

随机推荐

  1. Vijos 1451 圆环取数 【区间DP】

    背景 小K攒足了路费来到了教主所在的宫殿门前,但是当小K要进去的时候,却发现了要与教主守护者进行一个特殊的游戏,只有取到了最大值才能进去Orz教主…… 描述 守护者拿出被划分为n个格子的一个圆环,每个 ...

  2. HDU 5762Teacher Bo

    Teacher Bo Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tota ...

  3. nginx开发(四)调用ffmpeg,搭建rtmp直播流。

    1: 修改conf文件,配置rtmp直播 打开usr/local/nginx/conf/nginx.conf,添加红色内容: rtmp {#rtmp点播配置    server {        li ...

  4. 10. Extjs Button控件的handler配置项和click事件

    转自:https://blog.csdn.net/lishk314/article/details/41541797 查看API: click( this, e, eOpts ) Fires when ...

  5. 提交图片base64格式问题

    提交图片base64格式给后台,一定把data:image/png;base64,去掉,不然提交后后台返回的图片URL打开是一个破坏的图片.使用split("base64,")[1 ...

  6. LVS集群体系和调度算法

    集群体系和调度算法 LVS集群体系架构 1)使用LVS架设的服务器集群系统有三个部分组成: 最前端的负载均衡层,用Load Balancer表示, 中间的服务器群组层,用Server Array表示, ...

  7. bzoj 1682: [Usaco2005 Mar]Out of Hay 干草危机【并查集+二分】

    二分答案,把边权小于mid的边的两端点都并起来,看最后是否只剩一个联通块 #include<iostream> #include<cstdio> using namespace ...

  8. P3256 [JLOI2013]赛车

    传送门 如果把速度看成斜率,起始位置看成截距,这就是一个水平可见直线了-- 不过这题里我实现方法借鉴了CQzhangyu大佬的,先按速度排序,然后维护一个单调栈,如果当前的人速度比栈顶大距离又比它远直 ...

  9. sublime text2 配置php本地环境时遇到的错误。

    首先,将PHP加到电脑的环境变量中如图(D:\PHPEnv\PHP5是我PHP的安装目录): 第二步:添加编译系统配置 第三步:配置详情: { "cmd": ["php. ...

  10. 如何保证access_token长期有效--微信公众平台开发

    http://blog.csdn.net/qq_33556185/article/details/52758781 import javax.servlet.ServletContext; impor ...