转自作者:phylips@bmy
出处:http://duanple.blog.163.com/blog/static/709717672008102885325526/
poj 1275 3159 1364 1716 1201 3169
这类问题,就像网络流,图论,dp,关键在列出满足的表达式,建立好数学模型,剩下的过程就很简单了。所以主要难点在于构图,从实际的描述抽象成模型。准确找到约束条件。
关于基础知识可以查看clrs 22.4节。下面只介绍我遇到的一些问题和理解。
所谓的差分约束系统,实际上指一系列的表达式,满足 形如{ xi - xj <= a}
求解实际上转化成了图论里的一个等价问题,最短路问题,实际上巧妙的利用了最短路具有的性质 di - dj <= w(j,i)
如果这样的最短路求成来了,他们的值便可以直接作为xi xj的一组可行解。
图论里求最短路,有很多方法,差分约束系统,一般利用的是单源最短路,而在单源最短路算法中,常见的是dijkstra和bellman-ford算法。这两个算法各有优劣。
dijkstra算法,效率比较高,如果用堆实现,可以达到O(vlogv+E)的复杂度,但是它只能解决正边权类型的问题,对于负边权的问题,必须采用bellman-ford算法,它的复杂度是VE.
bellman-ford算法很强大,不单可以求最短路,还可以求最长路。一般如果约束条件是 <=形式的,就标志着要求最短路,>=则要通过求最长路解决。
当然这两种约束是可以转化的,因为 xi - xj <= a实际上等价于xj- xi >= a。
一.优化途径:
1.如果改变边的松弛(relax)顺序,程序的执行顺序会有很多改观
2.当所有边都不能再松弛的时候,便可以跳出循环了,不必全部循环V-1次
这些可以通过poj1716 1201体验到
二.关于Dist[]的初始化化
1.如果将源点到各点的距离初始化为0,最终求出的最短路满足 它们之间相互最接近了
2.如果将源点到各点的距离初始化为INF(无穷大),其中之1为0,最终求出的最短路满足 它们与该点之间相互差值最大。
这些可以从poj3169 layout 得到证实。
三.
关于dikstra算法的堆实现,有两种策略,一种是一开始把全部节点放到堆里,为每个节点维护一个在堆里的索引数组。另一种策略是当当前点被更新才放到堆里,但是要注意标记已经求得最短路的哪些点,避免重复求值。
我采用的是第一种策略,去求解的poj3159 Candies
当然还有一个优化是,如果已经找到了目标点,就可以退出了,不必全部求出最短路
四.陷阱
int a[MAX] =  {INF};
注意a里面的元素只有第一个会被赋为INF,其他会被赋为0,而不是INF。
关于模型的建立,其实,很多情况下我们的 xi都是一个和式,比如从开头到现在的某个量的积累值,比如poj1716 1201中,我们要定义x[i]为点集里小于i的数的个数,则x[j] - x[i]则表示了落在线段区间[i,j]的点的个数。还有poj1364 King 也是类似,另外一些可能就是比较简单的直接的约束关系。
比较复杂的如poj1275 Cashier Employment
这个问题比较特殊,乍看其他上述问题都是寻找最小数目的点,使这些点可以覆盖线段。而这个则是找一些数目的人,而人实际上是一些线段,使这些线段可以在那些特点的总数目可以满足要求并且数目最少。关键在定义一个状态,这里如果大胆定义i时刻出纳员数目s[i],就可以了,然后利用这个s[i]便可以找到所有的约束关系,并列出不等式,这样模型就建立好了。
这个可以参考刘汝佳的书P307,图论最短路那部分,刚好以这个问题为例,而且这个问题求的就是最长路。对于sum可以二分进行优化,不过我直接穷举也过了。
poj3159 Candies
这是我接触差分约束的第一题。设S[a]为kid a获得的candies数,则每一行代表的约束是S[b]-S[a]<=c,目标函数是使得S=S[N]-S[1]最大。
利用差分约束的思想建图,对于每一条约束,从a向b做一条长为c的边,则从1到N的最短路即为所求。由于本题c皆为非负数,所以可以用Dijkstra高效解决。
转自作者:phylips@bmy的更多相关文章
- 转债---Pregel: A System for Large-Scale Graph Processing(译)
		
转载:http://duanple.blog.163.com/blog/static/70971767201281610126277/ 作者:Grzegorz Malewicz, Matthew ...
 - LevelDB:一个快速轻量级的key-value存储库(译)
		
作者:Jeff Dean, Sanjay Ghemawat 原文:http://leveldb.googlecode.com/svn/trunk/doc/index.html 译者:phylips@b ...
 - 从LSM-Tree、COLA-Tree谈到StackOverflow、OSQA
		
转自: http://blog.csdn.net/v_july_v/article/details/7526689 从LSM-Tree.COLA-Tree谈到StackOverflow.OSQA 作者 ...
 - 分布式理论(4):Leases 一种解决分布式缓存一致性的高效容错机制(转)
		
作者:Cary G.Gray and David R. Cheriton 1989 译者:phylips@bmy 2011-5-7 出处:http://duanple.blog.163.com/blo ...
 - 浏览器内部工作原理--作者:Tali Garsiel
		
本篇内容为转载,主要用于个人学习使用,作者:Tali Garsiel 一.介绍 浏览器可以被认为是使用最广泛的软件,本文将介绍浏览器的工作原理,我们将看到,从你在地址栏输入google.com到你看到 ...
 - Eclipse自动生成作者、日期注释等功能设置
		
我们在使用Eclipse 编写Java代码时,自动生成的注释信息都是按照预先设置好的格式生成的. 修改作者.日期注释格式:打开Windows->Preferences->Java-> ...
 - SVN如何查看修改的文件记录]	           来源:Linux社区     作者:frogoscar
		
SVN如何查看修改的文件记录 [日期:2014-11-20] 来源:Linux社区 作者:frogoscar [字体:大 中 小] 主要是有四个命令,svn log用来展示svn 的版本作者 ...
 - 《C++ API设计》作者Martin Reddy访谈问题征集
		
Martin Reddy博士是软件行业的一名老兵,有着15年以上的从业经验,共撰写过40多篇论文,拥有3项软件专利,并与他人合著了Level of Detail for 3D Graphics.另外, ...
 - XCode修改公司名称和作者名称
		
新建的文件最上方都会有一段类似如下的版权声明 // // ViewController.m // CBDemoProject001 // // Created by CB on 16/3/17. ...
 
随机推荐
- How to: Reading an ini config file from a batch file
			
Original Link: http://almanachackers.com/blog/2009/12/31/reading-an-ini-config-file-from-a-batch-fil ...
 - hdu 1715 大菲波数(高精度数)
			
Problem Description Fibonacci数列,定义如下: f(1)=f(2)=1 f(n)=f(n-1)+f(n-2) n>=3. 计算第n项Fibonacci数值. Inpu ...
 - 简单模拟java动态动态代理机制的底层实现原理
			
在网上学习了马士兵老师的设计模式视屏,过程中也有认真的做相应的笔记.在次分享我的一些成果,方便大家的进一步学习. 1.接口 } 2.被代理的对象 public class Tank implemen ...
 - JDBC访问SQLServer2008数据库
			
来源:十二随风博客 由JDBC驱动直接访问数据库优点:100% Java,快又可跨平台缺点:访问不同的数据库需要下载专用的JDBC驱动 (1)下载对应数据库版本的jdbc驱动并安装,注意安装后的得到的 ...
 - JavaScript的事件监听、捕获和冒泡
			
在前端开发中,我们经常需要对某些事件进行监听.这样只要在指定的元素上触发了该事件,就会执行一个回调函数来进行相关的操作. 而JavaScript中事件监听的方法总共有三种,分别如下: element. ...
 - 基于bootstrap3的 表格和分页的插件
			
如题 样式呢就是bootstrap3 的 功能呢就是实现表格和分页 (以上废话) 本来是自己没事儿写的一个js插件,曾经搁浅了一阵子,但最近由于公司项目的原因也需要这样的一个插件,所以就捡起来做了个可 ...
 - hybird app
			
Hybrid App 是混合模式应用的简称,兼具 Native App 和 Web App 两种模式应用的优势,开发成本低,拥有 Web 技术跨平台特性.目前大家所知道的基于中间件的移动开发框架都是采 ...
 - c#抽象工厂类
			
抽象工厂类的结构如下: 工厂 a=new 1工厂 抽象类A aa=a.createA() aa.create()==类A1.create() 抽象类B bb=a.createB() bb.get()= ...
 - ACE_linux:读写锁
			
1.涉及类 ACE_RW_Thread_Mutex //ACE读写锁ACE_Read_Guard //ACE加读锁ACE_Write_Guard //ACE加写锁ACE_Thread_Manager ...
 - sum_series() 求一列数的指定个数的数和(5个数字的和)
			
#include <stdio.h> #include <stdarg.h> /*用sum_series() 求一列数的指定个数的数和(5个数字的和)*/ double sum ...