Josephus Problem
2013-05-28 17:49
176 查看
问题描述:
n个罪犯被一群人追杀,为了不被敌人杀死,n个罪犯决定通过如下的方式自杀:手拉手围成一圈,并对每个人按顺序编号为:1,2,3,...,n。
从1开始报数,报到k的那个人就自杀,再从自杀的下一个人继续从1开始报数,以此类推,我们能够知道最后幸存的那个人的编号吗?
解决方法:
通过DP能够在$O(n)$解决问题。
首先我们需要递推式:
设$f(n,k)$表示有n个人且报到k的人自杀的情况下,最后幸存的人的编号。
\[f(n,k)=(f(n-1,k)+k - 1)\%n + 1\]
其中 $f(1,k) = 1$。
如果有 $n$ 个人且报到 $k$ 的人自杀时,第一个自杀的人一定是编号为 $(k-1) \% n + 1$ 的人,因此剩下还有$n-1$ 个人,把 $f(n,k)$ 想象成一个子程序,你能够调用它,我们只需要把剩下的 $n-1$ 个人重新编号,就能用 $f(n-1,k)$ 解决了。重新编号如下:
原来的编号 1 2 ... k-1 k+1 k+2 ... n
现在的编号 n-k+1 n-k+2 n-1 1 2 n-k
假设现在编号为 $i$,则原来的编号为$(i+k-1) \% n + 1$(注意,这里不是(i+k) mod n,因为当i=n-k时,(i+k) mod n = 0)。
如果按照“现在的编号”的方式,用 $f(n-1,k)$ 能够找到幸存者,因此再将“现在的编号”转换成原来的编号即可,即 $f(n,k)=(f(n-1,k)+k - 1)\%n+1$
另解:如果按照 0,1,2,...,n-1 编号,则递推式变成了:
\[f(n,k)=(f(n-1,k)+k)\%n\]
其中$f(1,k)=0$
代码实现:
Josephus的Java实现
复杂度:$O(n)$
n个罪犯被一群人追杀,为了不被敌人杀死,n个罪犯决定通过如下的方式自杀:手拉手围成一圈,并对每个人按顺序编号为:1,2,3,...,n。
从1开始报数,报到k的那个人就自杀,再从自杀的下一个人继续从1开始报数,以此类推,我们能够知道最后幸存的那个人的编号吗?
解决方法:
通过DP能够在$O(n)$解决问题。
首先我们需要递推式:
设$f(n,k)$表示有n个人且报到k的人自杀的情况下,最后幸存的人的编号。
\[f(n,k)=(f(n-1,k)+k - 1)\%n + 1\]
其中 $f(1,k) = 1$。
如果有 $n$ 个人且报到 $k$ 的人自杀时,第一个自杀的人一定是编号为 $(k-1) \% n + 1$ 的人,因此剩下还有$n-1$ 个人,把 $f(n,k)$ 想象成一个子程序,你能够调用它,我们只需要把剩下的 $n-1$ 个人重新编号,就能用 $f(n-1,k)$ 解决了。重新编号如下:
原来的编号 1 2 ... k-1 k+1 k+2 ... n
现在的编号 n-k+1 n-k+2 n-1 1 2 n-k
假设现在编号为 $i$,则原来的编号为$(i+k-1) \% n + 1$(注意,这里不是(i+k) mod n,因为当i=n-k时,(i+k) mod n = 0)。
如果按照“现在的编号”的方式,用 $f(n-1,k)$ 能够找到幸存者,因此再将“现在的编号”转换成原来的编号即可,即 $f(n,k)=(f(n-1,k)+k - 1)\%n+1$
另解:如果按照 0,1,2,...,n-1 编号,则递推式变成了:
\[f(n,k)=(f(n-1,k)+k)\%n\]
其中$f(1,k)=0$
代码实现:
public class Josephus { public static int josephus0(int n,int k){ int r = 0; for(int i=2;i<=n;i++){ r = (r + k) % i; } return r; } public static int josephus1(int n,int k){ int r = 1; for(int i=2;i<=n;i++){ r = (r + k - 1) % i + 1; } return r; } public static void main(String[] args) { System.out.println(josephus1(10000,2)); } }
Josephus的Java实现
复杂度:$O(n)$
相关文章推荐
- 湘潭市赛 Josephus Problem 线段树
- 约瑟夫问题Josephus problem
- 约瑟夫问题(Josephus problem)
- 约瑟夫问题(Josephus problem)2:某人何时出列
- Josephus Problem的详细算法及其Python, Java语言的实现
- Josephus Problem
- lightoj 1179 - Josephus Problem 约瑟夫环
- 湘潭市赛 Josephus Problem 线段树
- 约瑟夫问题(Josephus Problem)
- 约瑟夫问题(Josephus Problem)3:谁最后一个出列
- 约瑟夫环问题(josephus problem)详解
- 约瑟夫问题(Josephus Problem)的两种快速递归算法
- 湘潭市赛 Josephus Problem 线段树
- 约瑟夫问题(Josephus Problem)4:第k个出列的人是谁
- Josephus problem
- lightoj1179 - Josephus Problem&&hdoj2211【约瑟夫环】
- 约瑟夫问题(Josephus problem)的一点思考
- 湘潭市赛 Josephus Problem 线段树
- 约瑟夫环问题(Josephus Problem)C程序实现
- 约瑟夫问题(Josephus Problem)