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

来源:互联网 发布:mac打开xlsx 编辑:程序博客网 时间:2024/05/22 13:49

问题描述:The Joseph's problem is notoriously known. For those who are notfamiliar with the original problem: from among n people, numbered 1, 2,. . ., n, standing in circle every mth is going to be executed and onlythe life of the last remaining person will be saved. Joseph was smartenough to choose the position of the last remaining person, thus savinghis 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 circlethe first k are good guys and the last k bad guys. You have todetermine such minimal m that all the bad guys will be executed beforethe 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。