【ACM】Spring Outing
2016-04-09 04:29
337 查看
比较喜欢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]的值)。
再仔细想想,看似很难的题目,如果从最后一个人开始思考,也就是从树的树叶结点开始往回推,整个思路就非常清晰了!借用诸葛孔明一句话,这道题,“实在是妙啊”!
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析