二分法浅谈 (1)

[问题描述]

有N头奶牛(N是2K),都是网球高手,每头奶牛都有一个BTP排名(恰好为1—N)。下周将要进行一场淘汰赛,N头奶牛分成N/2组,每组两头奶牛比赛,决出N/2位胜者;N/2位胜者继而分成N/4组比赛……直至剩下一头牛是冠军。

比赛既要讲求实力,又要考虑到运气。如果两头奶牛的BTP排名相差大于给定整数K,则排名靠前的奶牛总是赢排名靠后的;否则,双方都有可能获胜。现在观众们想知道,哪头奶牛是所有可能成为冠军的牛中排名最后的,并要求你列举出一个可能的比赛安排使该奶牛获胜。(限制N≤65536)

[分析]

由于N很大,我们猜想可以通过贪心方法解决。

我们希望排名靠前的选手总是“爆冷”输给排名靠后的选手。于是我们让1输给K+1、2输给K+2……每一轮中每一局总是选择未比赛的排名最前的选手,输给一个排名最靠后的选手(如果有的话)。

但我们很容易找到反例,例如:N=8, K=2,由上述贪心方法我们得到对阵方式结果为4,见图BTP-1(其中XàY表示X战胜Y)。

    图BTP-1                                            图BTP-2

但最优解为6,见图BTP-2。究其原因,因为我们不知道最优解是多少,所以我们是在盲目地贪心。事实上,最优解的6在第一轮就被我们淘汰了,当然就得不到最优解喽!

要想知道最优解?枚举!同时考虑到一个很显然的结论——如果排名为X的选手最终获胜,那么排名在X前的选手也可以获胜

显然归显然,证明它我们还需要动一点小脑筋。假设排名X的选手最终获胜,我们通过对该对战方式的局部修改,构造出一种新的对战方式使任意排名Y<X的选手获胜:在X最终获胜的对战方式中,假设Y是被Z击败。如果Z≠X,由X>Y,可知Z一定也能击败X,且同一轮及此后X所击败的选手都能被Y击败,所以我们只需要在此轮让Z击败X,并把之后所有对战中的X都改成Y即可;如果Z=X,由X>Y,我们就让Y击败X,同样把之后对战中的X都改成Y,则最后获胜的也是Y。

因此,我们就可以用二分枚举最终获胜的X,大大提高了算法效率。

现在的问题是,如果我们知道最终获胜的是X,我们能否很快构造出一种对战方式或是证明不存在吗?可以,我们仍旧使用贪心,不过因为我们知道最终谁获胜,所以我们采用倒推。

每一轮,我们都让已有选手去战胜一个排名最靠前的还未出现的选手,由该方法产生的对战方式就如图BTP-2所描述那样。至于最靠前的未出现选手如何找,我们可以采用静态排序二叉树实现,这里不再展开,读者可以自己考虑。

可以证明这样贪心是正确的(证明方法同前面的证明类似,这里也不再重复)。整个问题可以在O(Nlog2N)时间完成。

[小结]

对于这类需要二分枚举的问题,其实算法的根本是在一个隐含的退化了的有序序列中进行二分查找,只是这个序列仅含有0和1两种值。上例中当X<Ans,A[X]=0;当X≥Ans,A[X]=1。而我们所寻找的就是这两种值的分界点。有了分界点,就有了最优值,也就有了原问题的解。


posted on 2010-08-09 14:44 蓝色的大海 阅读(155) 评论(0)  编辑 收藏 引用 所属分类: ACM


只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理


<2026年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿

文章分类

文章档案

搜索

最新评论