夜鱼的专栏

全纯人群,留迹数域。

约瑟夫 (Joseph) -- ACM PKU 1012 解题报告

问题描述:The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved.
Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.

参见 http://acm.pku.edu.cn/JudgeOnline/problem?id=1012

我的总体思路是,对从每个 m=k+1, k+2, ... ,计算出前 k 个被杀的人,如果他们的编号都比 k 大,则表示所有所有坏人都被杀掉了,从而找到了最小的 m。

用 rest 表示还有多个人活着,初值为 2k。当 start 表示当前轮从哪个编号开始计算,初值为 1。用 killed 表示当前轮要被杀的人的编号。则 killed = (start - 1+ m) mod rest。这时,对 killed 后面的人进行重新编号:killed+1 -> killed,killed+2 -> killed+1,..., rest -> rest -1。即被执行的那个人的后面所有的编号都递减 1。在新的编号下,新的开始计算编号为 start = killed。以此反复直到某一轮中, killed <= 4 或只剩下 k 个人。如果是后者,则 m 为解。这个算法的关键在于,在新的编号下,好人的编号都是不变的。而坏人的编号可能一直在变化,而正是我们不关心坏人的编号变化情况,才使得这算法成立。在真正的实现中,并不需要真的去把被杀者的后面的人的编号都递减 1,原因就我刚才说的,我们不必关心坏人的编号变化。

此题是经典 Joseph 的一个变体。最原始的题目正是题目描述的第一部分,即求最后的幸存者,可以用动态规划求解。

假设第一个被杀的人为 k = m mod n。接着,我们对所有人都进行重新编号:k+1 mod n -> 1, k+2 mod n -> 2,k+x mod n -> x,...,k-1 mod n -> n-1。则问题变了只剩下 n-1 个人的情况。假设在这个新的编号下的 n-1 人中,最后幸存的是 x,则从上面的映射可知,其原来的编号为 (x + k) mod n。记 f(n) 为在 n 个人的 Joseph 问题中幸存者的编号,则 f(n) = (f(n-1)+m) mod n。而 f(1) = 1。当 m=2 时,f(n) 有解析解,详见 http://en.wikipedia.org/wiki/Josephus_problem。

 

阅读更多
文章标签: rest 算法
个人分类: 趣味题目
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭