zoj2770(差分约束)火烧连营
来源:互联网 发布:转行程序员基础书籍 编辑:程序博客网 时间:2024/04/26 08:27
差分约束详细解释见电子书
例 4.13 火烧连营(Burn the Linked Camp)
ZOJ Monthly, October 2006, ZOJ2770
题目描述:
大家都知道,三国时期,蜀国刘备被吴国大都督陆逊打败了。刘备失败的原因是刘备的错误
决策。他把军队分成几十个大营,每个大营驻扎一队部队,又用树木编成栅栏,把大营连成一片,
称为连营。
让我们回到那个时代。陆逊派了很多密探,获得了他的敌人-刘备军队的信息。通过密探,
他知道刘备的军队已经分成几十个大营, 这些大营连成一片(一字排开), 这些大营从左到右用 1…
n 编号。第 i个大营最多能容纳 Ci个士兵。而且通过观察刘备军队的动静,陆逊可以估计到从第 i
个大营到第 j 个大营至少有多少士兵。最后,陆逊必须估计出刘备最少有多少士兵,这样他才知
道要派多少士兵去烧刘备的大营。
输入描述:
输入文件中有多个测试数据。每个测试数据的第一行,有两个整数 n(0<n≤1000)和m(0≤m
≤10000)。第二行,有n 个整数 C1…Cn。接下来有m 行,每行有 3个整数 i, j, k(0<i≤j≤n, 0≤
k<231),表示从第i 个大营到第 j个大营至少有 k 个士兵。
输出描述:
对每个测试数据,输出一个整数,占一行,为陆逊估计出刘备军队至少有多少士兵。然而,
陆逊的估计可能不是很精确,如果不能很精确地估计出来,输出"Bad Estimations"。
样例输入: 样例输出:
3 2
1000 2000 1000
1 2 1100
2 3 1300
3 1
100 200 300
2 3 600
1300
Bad Estimations
分析:
以样例输入中第 1 个测试数据为例解释差分约束系统的构造及求解。其数学模型为:设3 个
军营的人数分别为 A1、 A2、 A3,容量为C1、 C2、C3,前 n个军营的总人数为 Sn,则有以下不
等式组:
1) 根据第 i个大营到第 j 个大营士兵总数至少有k 个,得不等式组(1):
S2 – S0 >= 1100,等价于:S0 – S2 <= -1100
S3 – S1 >= 1300,等价于: S1 – S3 <= -1300
2) 又根据实际情况,第 i 个大营到第 j 个大营的士兵总数不超过这些兵营容量之和,设d[i]为
前 i 个大营容量总和,得不等式组(2):
S2 – S0 <= d[2] – d[0] = 3000
S3 – S1 <= d[3] – d[1] = 3000
3) 每个兵营实际人数不超过容量,得不等式组(3):
A1 <= 1000,等价于: S1 – S0 <= 1000
A2 <= 2000,等价于: S2 – S1 <= 2000
A3 <= 1000,等价于: S3 – S2 <= 1000
4) 另外由 Ai>=0,又得到不等式组(4):
S0 – S1 <= 0
S1 – S2 <= 0
S2 – S3 <= 0
本题要求的是 A1 + A2 + A3的最小值,即 S3 – S0 的最小值。
有向网的构造:首先每个 Si 对应到有向网中的一个顶点Vi;然后对上述 4个不等式组中的每
一个不等式: Si – Sj <= c,转化成从Sj 到 Si的一条有向边,权值为 c。由不等式组(1)和(2)可知,
存在<Sj, Si-1>和<Si-1, Sj>双向边,只是权值不一样;由不等式组(3)和(4)可知,存在<Si, Si+1>
和<Si+1, Si>双向边,只是权值不一样。构造好的有向网如图4.29 所示。
构造好网络之后,最终要求什么?要求的是S3 – S0 的最小值,即要求不等式:
S3 – S0 >= M
中的约束 M,并且M 取其最大值,转化成:
S0 – S3 <= -M
即求 S3 到S0 的最短路径(最小值),长度为-M,求得-M为-1300,即M 为 1300(M的最大值)。
对样例输入中的第 2 个测试数据,对应差分系统中的不等式及构造的有向网如图4.30 所示。
为什么这个测试数据的输出为"Bad Estimations"?在Bellman-Ford 算法中,执行完本身的2
重循环之后,还应该检查每条边<u,v>,判断一下:加入这条边是否会使得顶点v 的最短路径值再
缩短,即判断: dist[u] + w(u,v) < dist[v]是否成立,如果成立,则说明存在从源点可达的负权值回
路。这时应该输出"Bad Estimations"。
//差分约束,又特么的数学建模//这个建模很经典啊,这个建模有点麻烦啊//最后建模后,一个推导成了n到0的最短路径//spfa+slf优化#include<cstdio>#include<iostream>#include<cstring>#include<queue>using namespace std;const int mn=2000,mm=42000;//mm开小了,re了我半天 struct Edge{ int to,w,next;} edges[mm];int head[mn],tot,n,m;long long dis[mn];long long sum[mn];void add(int u,int v,long long w){ edges[tot].w=w; edges[tot].to=v; edges[tot].next=head[u]; head[u]=tot++;}int cnt[mn];//记录进队列的次数bool inq[mn];//标志是否在队列中deque<int> q;bool spfa(){ //计算n的单源点最短路 memset(cnt,0,sizeof(cnt)); memset(dis,6,sizeof(dis)); memset(inq,false,sizeof(inq)); dis[n]=0,cnt[n]=inq[n]=true; q.clear(); q.push_back(n); while(q.size()) { int x=q.front(); q.pop_front(); inq[x]=false; for(int i=head[x]; ~i; i=edges[i].next) { int v=edges[i].to; if(dis[v]>dis[x]+edges[i].w) { dis[v]=dis[x]+edges[i].w; if(!inq[v]) { if(++cnt[v]==n) return false; inq[v]=true; if(q.size()&&dis[v]<dis[q.front()]) q.push_front(v); else q.push_back(v); } } } } return true;}int main(){ int u,v,w; while(~scanf("%d%d",&n,&m)) { tot=0; memset(head,-1,sizeof(head)); for(int i=1; i<=n; ++i) { scanf("%d",&u); sum[i]=sum[i-1]+u; add(i-1,i,u); add(i,i-1,0); } for(int i=1; i<=m; ++i) { scanf("%d%d%d",&u,&v,&w); add(v,u-1,-w); add(u-1,v,sum[v]-sum[u-1]); } if(spfa()) printf("%lld\n",-dis[0]); else puts("Bad Estimations"); } return 0;}
- ZOJ2770,火烧连营,差分约束
- zoj2770(差分约束)火烧连营
- ZOJ2770 差分约束
- zoj2770 差分约束
- zoj2770解题报告(差分约束)
- zoj2770,差分约束系统
- ZOJ2770-Burn the Linked Camp(差分约束系统)
- ZOJ2770 Burn the Linked Camp(差分约束)
- ZOJ2770:Burn the Linked Camp(差分约束)
- 差分约束入门题ZOJ2770&&AOJ517
- ZOJ2770 Burn the Linked Camp,差分约束
- zoj2770 Burn the Linked Camp --- 差分约束
- 约分差束 例题 ZOJ 2770 火烧连营
- 火烧连营
- zoj2770 Burn the Linked Camp 差分约束和最短路bellman
- ZOJ2770 Burn the Linked Camp (差分约束与最短路)
- ZOJ1508 (差分约束)
- hdu3592(差分约束)
- HDU6304(Balala Power!)
- Source Tree for Mac 不断提示输入密码
- [Scala]Scala学习笔记三 Map与Tuple
- 线程特性以及常用术语
- 小程序及语音转文字
- zoj2770(差分约束)火烧连营
- Linux内存管理
- 实现自定义的Web服务器
- 《sqlmap教程一:命令》
- 微信企业号开发之网页授权接口调用示例
- 12-filter
- python组合数据类型--集合
- C#的输入输出流
- HDU6034 Balala Power! (字符串)