【ACM】Spring Outing

比较喜欢hihocoder.com这个oj,上面每周都有竞赛题,算法往往不难,甚至有的其实很基础;但是,它的解题思路妙就妙在,往往看似很难解决的题目,换一个角度去思考,就有非常简单而且非常优美的解答,实在适合当作脑经急转弯呵!比如这次这题:Spring Outing

Question

有n个人对决定出去游玩,他们有m个备选的游玩地点(1..m)或者选择干脆宅在家(0)。每个人在自己心目中对这m+1(0..m)个地点有一个排名,他们会根据这个列表进行投票。

对于m个地点,按1,2,3,...,m的顺序依次进行表决。当某一个方案票数超过一半时,则投票结束,选择这个地点作为结果。如果m个地点都没有超过半数,那就选择每个人都宅在家里。

现在将每一个人心目中的排名公布出来,即每个人都知道所有人对于m+1个地点的排名。同时他们都非常聪明,会尽量让自己更喜欢的地点胜出,求问最后会选择哪一个地方作为游玩地点。


Hint:

本题的关键在于想明白每个人是如何决策的。原题在Hint中针对样例数据简单(有点模糊)地解释了每个人是如何决策的,对我们有一定的提示作用。请原谅出题人不能在Hint中解释得更加清楚——如果解释得更加清楚的话,基本上就是把解法讲明了。:P

如果我们从最后一轮(对地点m的)投票开始分析,每个人的决策就会一目了然。

假设我们已经进行到了最后一轮,需要对地点m进行投票。这时每个人都知道:如果地点m没有超过半数,那么最终的结果就是宅在家里(地点0)。于是所有认为m比0好的人必然投赞成票,而所有认为0比m好的人必然投反对票。所以如果进入到了最后一轮,那么最终选出的地点是确定的,我们不妨记为result[m]。(如果赞成票多于反对票,那么result[m]=m,否则result[m]=0。对于确定的输入数据,result[m]是唯一确定的。)

现在假设我们进行到倒数第二轮,需要对地点m-1进行投票。根据以上分析,这时每个人都知道:如果地点m-1没有超过半数,那么最终的结果就是result[m]。于是所有认为m-1比result[m]好的人必然投赞成票,而所有认为result[m]比m-1好的人必然投反对票。最终选出的地点也是确定的,我们不妨记为result[m-1]。

以此类推,我们可以求得result[m-2], result[m-3], ..., result[2], result[1]。其中result[1]就是本题的答案。


Solution:


整个过程写成伪代码为:

result = 0
For i = m .. 1
    vote = 0
    For j = 1 .. n
        If (rank[j][i] < rank[j][result]) Then
            vote = vote + 1
        End If
    End For
    If (vote > n / 2) Then
        result = i
    End If
End For

其中rank[j][i]表示表示第j个人心中,地点i的排名,值越小越靠前;同时把result数组简化为一个变量(这是由于计算result[i]时只需要result[i+1]的值)。


再仔细想想,看似很难的题目,如果从最后一个人开始思考,也就是从树的树叶结点开始往回推,整个思路就非常清晰了!借用诸葛孔明一句话,这道题,“实在是妙啊”!

你可能感兴趣的:(算法,ACM)