题目:

Sample Input
2
2 3 4 2
96 97 199 62
Sample Output
2 2
9859 62

题意:

有三个杯子它们的容量分别是a,b,c, 并且初始状态下第一个和第二个是空的, 第三个杯子是满水的。可以把一个杯子的水倒入另一个杯子,当然,当被倒的杯子满了或者倒的杯子水完了,就不能继续倒了。

你的任务是写一个程序计算出用最少的倒水量,使得其中一个杯子里有d升水。如果不能倒出d升水的话,那么找到一个d' < d ,使得d' 最接近d。

分析:

  可以把每个状态即3个水杯里的水的数量的状态看成一个点,两个状态之间的转换关系(即A状态转移k升水后变成B状态)建边,边权为转移的水的升数。然后用spfa求最短路。最后从d开始for到0,看一下那一个状态是可以到达的,然后输出即可。对于d>c的情况,直接输出0 c就可以了(因为无论如何杯子里最多只会有c升水,而且一开始的时候根本不用转移水就可以了)。因为数据范围是<=200,水的总和一定,所以只要知道前两个杯子的状态就能推出第三个杯子的状态,所以总点数会小于200*200(有些状态是不会出现的)。

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#include<queue>
#define INF 0xfffffff
#define Maxn 210 struct node
{
int x,y,c,next;
}t[Maxn*Maxn*];int len; bool inq[Maxn*Maxn]; int first[Maxn*Maxn],dis[Maxn*Maxn]; int mymin(int x,int y) {return x<y?x:y;} void ins(int x,int y,int c)
{
if(x==y) return;
t[++len].x=x;t[len].y=y;t[len].c=c;
t[len].next=first[x];first[x]=len;
} queue<int > q; void spfa(int s)
{
memset(inq,,sizeof(inq));
memset(dis,,sizeof(dis));
while(!q.empty()) q.pop();
inq[s]=;dis[s]=;q.push(s);
while(!q.empty())
{
int x=q.front();q.pop();inq[x]=;
for(int i=first[x];i;i=t[i].next)
{
int y=t[i].y;
if(dis[y]>dis[x]+t[i].c)
{
dis[y]=dis[x]+t[i].c;
if(!inq[y])
{
q.push(y);
inq[y]=;
}
}
}
}
} int ffind(int x,int c,int C)
{
int mn=INF;
for(int i=;i<=c-x;i++)
{
mn=mymin(mn,dis[i*C+c-x-i]);//-,-,d
mn=mymin(mn,dis[(c-x-i)*C+i]);//-,-,d
mn=mymin(mn,dis[x*C+c-x-i]);//d,-,-
mn=mymin(mn,dis[x*C+i]);//d,-,-
mn=mymin(mn,dis[i*C+x]);//-,d,-
mn=mymin(mn,dis[(c-x-i)*C+x]);//-,d,-
}
return mn;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(d>=c) {printf("0 %d\n",c);continue;}
len=;
memset(first,,sizeof(first));
int C=c+;
for(int i=;i<=c;i++)
for(int j=;i+j<=c;j++)
{
int k=c-i-j,st=i*C+j;
if(i<=b-j) ins(st,i+j,i);else ins(st,(i-b+j)*C+b,b-j);//1->2
if(i<=c-k) ins(st,j,i);else ins(st,(i-c+k)*C+j,c-k);//1->3
if(j<=a-i) ins(st,(i+j)*C,j);else ins(st,a*C+j-a+i,a-i);//2->1
if(j<=c-k) ins(st,i*C,j);else ins(st,i*C+j-c+k,c-k);//2->3
if(k<=a-i) ins(st,(i+k)*C+j,k);else ins(st,a*C+j,a-i);//3->1
if(k<=b-j) ins(st,i*C+j+k,k);else ins(st,i*C+b,b-j);//3->2
}
spfa();
for(int i=d;i>=;i--)
{
int x=ffind(i,c,C);
if(x<INF) {printf("%d %d\n",x,i);break;}
}
}
return ;
}

[UVA10603]

2016-04-09 10:13:24

【UVA10603】Fill (构图+最短路)的更多相关文章

  1. CF 787D Legacy(线段树思想构图+最短路)

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  2. UVa10603 Fill

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

  3. UVA-10603 Fill (BFS)

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

  4. 1.1.1最短路(Floyd、Dijstra、BellmanFord)

    转载自hr_whisper大佬的博客 [ 一.Dijkstra 比较详细的迪杰斯特拉算法讲解传送门 Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路.所以Dijkstra常常作为其他算 ...

  5. 最短路算法详解(Dijkstra/SPFA/Floyd)

    新的整理版本版的地址见我新博客 http://www.hrwhisper.me/?p=1952 一.Dijkstra Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路.所以Dijkst ...

  6. 【转】最短路&差分约束题集

    转自:http://blog.csdn.net/shahdza/article/details/7779273 最短路 [HDU] 1548 A strange lift基础最短路(或bfs)★254 ...

  7. Altium中Fill,Polygon Pour,Plane的区别和用法

    Fill:表示绘制一块实心的铜皮,将区域中的所有连线和过孔连接在一块,而不考虑是否属于同一个网络.假如所绘制的区域中有VCC和GND两个网络,用Fill命令会把这两个网络的元素连接在一起,这样就有可能 ...

  8. 转载 - 最短路&差分约束题集

    出处:http://blog.csdn.net/shahdza/article/details/7779273 最短路 [HDU] 1548    A strange lift基础最短路(或bfs)★ ...

  9. 最短路&查分约束

    [HDU] 1548 A strange lift 根蒂根基最短路(或bfs)★ 2544 最短路 根蒂根基最短路★ 3790 最短路径题目 根蒂根基最短路★ 2066 一小我的观光 根蒂根基最短路( ...

随机推荐

  1. Day05 - Python 常用模块

    1. 模块简介 模块就是一个保存了 Python 代码的文件.模块能定义函数,类和变量.模块里也能包含可执行的代码. 模块也是 Python 对象,具有随机的名字属性用来绑定或引用. 下例是个简单的模 ...

  2. grep参数说明及常用用法

    grep参数说明及常用用法 趁着午休的时间把自己经常使用的一些grep命令整理一下. 方便以后查看. 后续会逐步把awk/sed/find等常用的命令理一理. 增强下记忆. 也算是对得起自己了. ^^ ...

  3. centos emacs安装

    wget http://mirrors.ustc.edu.cn/gnu/emacs/emacs-24.5.tar.gz tar zxvf emacs-24.5.tar.gz cd emacs-24.5 ...

  4. centos 6.3 编译安装 nginx +mysql + php

    这篇文章是对另一篇文章的整理,作为记录收藏 1,配置防火墙,开启80端口.3306端口 配置iptables,开启80端口.3306端口 vi /etc/sysconfig/iptables -A I ...

  5. ASP.NET获取汉字首字母

    /// <summary> /// 获取汉字首字母(可包含多个汉字) /// </summary> /// <param name="strText" ...

  6. Android源码编译过程之九鼎开发板

    build_kernel() { # 进入源码顶层目录 cd ${BS_DIR_KERNEL} || # 编译配置文件 make ${BS_CONFIG_KERNEL} ARCH=arm CROSS_ ...

  7. ASP.Net免费发送短信-阿里大鱼短信接口

    有点短信余额 不用白不用 3月1号就过期了 情人节做了个免费发短信的 http://love.issuc.com/ 固定短信模板 [活动验证]您正在参加XXX的OOO活动,请确认系本人申请.需要的可以 ...

  8. Animating Layout Changes(展开收起)

    原文地址:https://developer.android.com/training/animation/layout.html#add (1)设置布局文件: <LinearLayout an ...

  9. Redhat linux DNS配置指南(SCANIP配置手册)

    在oracle 11g的RAC中增加了SCAN IP,而使用 SCAN IP的一种方式就是使用DNS,这里介绍在Redhat Linux 5.4中DNS的详细配置操作在配置DNS之前修改主机名Redh ...

  10. VS2008 未找到编译器可执行文件 csc.exe【当网上其他方法试玩了之后不起作用的时候再用这个方法】

    被公司派遣到中国海洋石油惠州炼化公司做项目,做的是生产管理,来了发现他们的项目结构简直烂的要命,和同学们写的毕业设计差不多,然后开发工具用的是vs2008,我电脑是安装了vs2005和vs2010,v ...