详细阐述约瑟夫环问题(报数出队问题)
来源:互联网 发布:mac抹掉进程失败 编辑:程序博客网 时间:2024/05/16 17:27
约瑟夫环问题(Josephus)
用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。(约瑟夫环问题 Josephus)
直接上代码:
1 #include <stdio.h> 2 int main() 3 { 4 int n, m, i, s = 0; 5 printf ("N M = "); 6 scanf("%d%d", &n, &m); 7 for (i = 2; i <= n; i++) 8 { 9 s = (s + m) % i;10 }11 printf ("\nThe winner is %d\n", s+1);12 }
刚接触这类问题的同学是不是有一种“我靠,为什么这么少”的感觉,然而只要这么少。
接下来讲解一下代码,既然作为一个经典的问题,那么此算法也当然不仅仅是对游戏过程的模拟了,更是对数学本质的一个分析。
为了讨论方便,先把问题稍微改变一下,并不影响原意:
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。
我们知道第一个出列的人编号一定是 m%n -1。那么剩下的n-1个人便可以看做组成了一个新的约瑟夫环(以编号为k=m%n的人开始):
k k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2并且从k开始报0。
现在我们把n-1个人的时候的编号做一下转换:
k --> 0
k+1 --> 1
k+2 --> 2
...
...
k-2 --> n-2
变换后就完完全全成为了(n-1)个人报数的子问题!(这便不是让我们倒推吗?)
假如我们知道这个子问题的解:例如A[n-1]是在n-1个人中的最终胜利者,那么根据上面对A[n-1]进行转换 便刚好就是n个人情况的解。变回去的公式很简单,如下:
A[n]=(A[n-1] +k)%n。(k是在n个人中第一个出列的人的编号,此处这个公式涉及了上面叙述到的编号的转换,需要搞懂了才能理解)
由于k=m%n,那么公式也可以写为A[n]=(A[n-1] +m)%n。为什么呢?很容易理解,7%3=1 , 1%3=1。
如此也是得出了递推公式:
A[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是A[n]
A[1]=0;
A[2]=(A[1]+m)%2;
A[i]=(A[i-1]+m)%i; (i>1)
有了这个公式,我们要做的就是从1-n顺序算出A[i]的数值,最后结果是A[n]。因为实际生活中编号总是从1开始,我们输出A[n]+1
由于是逐级递推,不需要保存每个A[i],于是便得到了最终的程序:
1 #include <stdio.h> 2 int main() 3 { 4 int n, m, i, s = 0; 5 printf ("N M = "); 6 scanf("%d%d", &n, &m); 7 for (i = 2; i <= n; i++) 8 { 9 s = (s + m) % i;10 }11 printf ("\nThe winner is %d\n", s+1);12 }
参考博客:http://blog.csdn.net/ZCSYLJ/article/details/6830703
本人博客,算法均为新手,闻过则喜,望各前辈不吝指点批评。
- 详细阐述约瑟夫环问题(报数出队问题)
- 报数问题(约瑟夫环)
- 报数(约瑟夫环问题)
- 约瑟夫环报数问题
- 约瑟夫环问题(报数问题)
- pku3750小孩报数问题(约瑟夫环问题)
- 约瑟夫环问题:圆桌报数问题
- 围圈报数问题(约瑟夫问题)
- 圆圈报数-约瑟夫问题
- 约瑟夫循环报数问题
- 【算法】约瑟夫环问题(报数出列)
- PHP实现 约瑟夫报数问题
- N人围圈,报数删除问题(约瑟夫问题)
- poj 3750 小孩报数问题 (约瑟夫问题)
- POJ-3750 小孩报数问题-约瑟夫问题
- 圆圈报数最后剩下的数 约瑟夫环问题 Joseph
- POJ 3750 小孩报数问题 模拟约瑟夫环
- 约瑟夫环 poj 3750 小孩报数问题 模拟
- servlet web 乱码问题透彻解决
- 第六周上机实践项目2——建立链栈算法库
- 关于OpenCV的那些事——相机姿态更新
- 第4周 项目4-建立双链表算法库
- 第三周项目三 求集合并集
- 详细阐述约瑟夫环问题(报数出队问题)
- 第四周 线性表(二)--链表 项目一 -- 建立单链表
- maints使用
- java编程思想-持有对象
- 第六周 周一 栈链
- Android UI SurfaceView的使用-绘制组合图型,并使其移动
- Oracle存储过程实例
- Ubuntu 14.04鼠标光标狂闪问题
- 第4周 项目3 - 单链表应用(1)