算法----约瑟夫环问题
2014-03-11 22:06
316 查看
约瑟夫环是一个数学的应用问题:
已知n个人(以编号0,1,2, ... n-1 分别表示)围坐在一张圆桌周围。从编号为0的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。求最后一个出列的人的序号。。
方法 1:
模拟游戏。利用数组或者循环链表,模拟游戏的进行,直到最后仅仅留下一个数。
复杂度是 O(MN)
方法 2: O(N)
1. 一开始,n 个人: 0 1 2 3 ... m-1
m m+1 ... n-1 显然,编号 m-1 的人出列;
||
\/
2. 新的序列:0 1 2 3 ... m-2 m m+1 ... n-1 从 编号 m 开始新的一轮游戏,
|| 因为从编号m开始,把后半段放到前面
\/
m m+1 ... n-1 0 1 2 ... m-2
|| 编号变换 <1>, 右半部分加上 n
\/
m m+1 ... n-1 n n+1 n+2 ... n+m-2
|| 编号变换 <2>, 全部减去 m
\/
0 1 2 3 .......X ............. n - 2
假设红色数字 X 是 [ 0 1 2 ... n-2] 中最终存留的序号,我们的目标是得到这个编号经过了两次编号变换前的编号 x'。
两次编号变换的逆变换其实就是 x' = (
X + m) % n;
因此,我们得到了递推关系式 f
= ( f[n-1] + m ) % n;
f[i] ---- 表示 i 个人玩这个游戏,最后存留的编号。
代码如下:
已知n个人(以编号0,1,2, ... n-1 分别表示)围坐在一张圆桌周围。从编号为0的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。求最后一个出列的人的序号。。
方法 1:
模拟游戏。利用数组或者循环链表,模拟游戏的进行,直到最后仅仅留下一个数。
复杂度是 O(MN)
方法 2: O(N)
1. 一开始,n 个人: 0 1 2 3 ... m-1
m m+1 ... n-1 显然,编号 m-1 的人出列;
||
\/
2. 新的序列:0 1 2 3 ... m-2 m m+1 ... n-1 从 编号 m 开始新的一轮游戏,
|| 因为从编号m开始,把后半段放到前面
\/
m m+1 ... n-1 0 1 2 ... m-2
|| 编号变换 <1>, 右半部分加上 n
\/
m m+1 ... n-1 n n+1 n+2 ... n+m-2
|| 编号变换 <2>, 全部减去 m
\/
0 1 2 3 .......X ............. n - 2
假设红色数字 X 是 [ 0 1 2 ... n-2] 中最终存留的序号,我们的目标是得到这个编号经过了两次编号变换前的编号 x'。
两次编号变换的逆变换其实就是 x' = (
X + m) % n;
因此,我们得到了递推关系式 f
= ( f[n-1] + m ) % n;
f[i] ---- 表示 i 个人玩这个游戏,最后存留的编号。
代码如下:
// copyright @ L.J.SHOU Mar.11, 2014 // jossef circle #include <iostream> #include <vector> using namespace std; int JosefCircle(int m, int n) { vector<int> f(n+1, 0); for(int i=2; i<=n; ++i) f[i] = (f[i-1] + m) % i; return f ; }
相关文章推荐
- 深入理解约瑟夫环的数学优化方法
- 批处理解约瑟夫环应用题代码
- java 实现约瑟夫环的实例代码
- 约瑟夫环问题(数组法)c语言实现
- 约瑟夫自杀环
- 约瑟夫环
- 循环链表实现Joseph环(约瑟夫环)猴子选大王类似问题
- 学习笔记——约瑟夫环
- <c++>利用deque容器,解决约瑟夫环问题
- 用数组和链表实现约瑟夫环问题
- 约瑟夫环的两种实现
- 南开百题难题破解(5)
- POJ3750 约瑟夫环
- 约瑟夫环问题 Java
- 约瑟夫环
- C语言循环链表求解约瑟夫环问题(循环方式)
- linux下用c语言实现约瑟夫环游戏
- USTCOJ 1366 市长选举(约瑟夫环变种)
- C++循环链表解决约瑟夫环问题,Qt编程
- 约瑟夫环,PHP模拟环形链解决方法!