关于“相邻交换法”

来源:互联网 发布:鸟哥php 编辑:程序博客网 时间:2024/06/07 06:01

相邻交换法(名字来自白书)主要解决元素排列问题,基本思路是先考虑两个元素如何决定先后,再推广到全体。
例1.NOIP2012国王游戏
容易发现对于相邻的i,j,若ai*bi>=aj*bj则i在j之前。
现在要推广到全体,需要先证明一个结论:
不妨把满足任意i在j之前的i,j都有ai*bi>=aj*bj称为S排列。
则S排列是最优排列。
证明:
易知对于相邻i,j,i在j之前,交换不影响其他元素,且若ai*bi<=aj*bj,把i,j交换一定不会变差,我们把这样的交换称为好操作。
只需证任意排列可以通过一系列好操作变成S排列,因为这意味着S排列不比任意排列差,即S排列是最优排列。
变换方法如下:对于一个排列,先挑ai*bi最大的,一路交换到最后,再挑第二大的,交换到倒数第二,以此类推。易知这当中的所有操作都是好操作。
从而S排列是最优排列,按ai*bi排序即可得到。

例2.UVa10905 Children’s Game
先考虑两个相邻元素A,B,设A的位数为LA,LB同理。
则若A*10^LB+B<=B*10^LA+A,那么A应在B之前。
同上,我们需要找S排列(也可能不存在)
对上式变形,有(10^LB-1)/B<=(10^LA-1)/A
那么(10^i-1)*i和例1的ai*bi是同理的,按它排序即可。

例3.二元流水作业调度问题
经典问题。
国际惯例先考虑两个相邻元素。
i在j之前的条件:min{bi,aj}>=min{bj,ai}
同样的问题:构造S排列。
遗憾的是上述条件和i,j都相关,没办法分成只与其中一个相关的量。
之前的办法行不通了。
只能再从上式入手。
发现:把所有ai,bi中最小的找出来,设它是ax,则由上式知任意元素都应排在x它之后,即它排最前。同理,若它是bx,则排最后。
像这样一直做下去,易知最后的排列是S排列,即最优排列。

0 0
原创粉丝点击