Josephus problem kill
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Josephus problem kill相关的知识,希望对你有一定的参考价值。
方便求解最后的胜利者同时也适合打印 出列 序列的,时间复杂度O(N).
下面方法借鉴自Java程序练习-约瑟夫环问题
public static int josepusONWithList(int n, int m) { return josepusONWithList(n, m, 1); } public static int josepusONWithList(int n, int m, int k) { if (n <= 0 || m <= 0 || k <= 0) return -1; LinkedList<Integer> list = new LinkedList<Integer>(); for (int i = 1; i <= n; i++) list.add(i); int outPos; while (list.size() > 1) { outPos = (int) (k + m - 2) % list.size(); // System.out.print(list.get(outPos)+" , "); list.remove(outPos); k = outPos + 1; } // System.out.println(list.get(0)); return list.get(0); }
在有时候需要知道出列的序列,上述System.out部分就是出列序列
首先我们通过思考可以得到一个很显然的结论,n个人时的获胜者和这n个人淘汰掉一个人继续游戏下的获胜者一定是同一个人。(有点像废话...)所以如果我们能确定 n-1个人时候的获胜者也就可以得到 n 个人时候的情况,因为两者的排列存在一种对应关系。
考虑n = 6 m = 3的情况
0 1 2 3 4 5
3 4 5 0 1 2
可以很明显的看出上下两行存在着 + m 模 n的对应关系。
这样这个问题就可以通过递推的方式解决了, f[i] 为 场上有 i 个人时,最后获胜者的编号(从零开始)。
那么就存在着这样的递推式 f[i] = ( f[i-1] + k ) % i 我们还可以知道 f[1] = 0 所以可以通过这个递推式轻松的得到答案啦~
public static int josephusON(int n, int m) { return josephusON(n, m, 1); } /** * Josephus 环的一个O(N)算法 * * @param n 总人数 * @param m 数到m的人出列 * @param k 开始报数人的编号 * @return 最后一个出列的编号 */ public static int josephusON(int n, int m, int k) { int p = 0; for (int i = 2; i <= n; i++) { // System.out.print((p + k == n ? n : (p + k) % n)+" "); p = (p + m) % i; } return (p + k) % n; // 返回最后一人的编号 }
以上是关于Josephus problem kill的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ - 1179 Josephus Problem(约瑟夫)
Bloomberg面经准备: Josephus problem
CF1257DYet Another Monster Killing Problem贪心
Educational Codeforces Round 76 (Rated for Div. 2) - D. Yet Another Monster Killing Problem(贪心)(示例代码
[Physics Kills Me]cls1277‘s Luogu solution and problems solved