检察机关门户网站建设情况,漳州项目工程交易中心网,校园推广文案,电子商务网站推广论文约瑟夫斯问题#xff08;有时也称为约瑟夫斯置换#xff09;#xff0c;是一个出现在计算机科学和数学中的问题。在计算机编程的算法中#xff0c;类似问题又称为约瑟夫环。 有n个囚犯站成一个圆圈#xff0c;准备处决。首先从一个人开始#xff0c;越过k-2个人#xff… 约瑟夫斯问题有时也称为约瑟夫斯置换是一个出现在计算机科学和数学中的问题。在计算机编程的算法中类似问题又称为约瑟夫环。 有n个囚犯站成一个圆圈准备处决。首先从一个人开始越过k-2个人因为第一个人已经被越过并杀掉第k个人。 接着再越过k-1个人并杀掉第k个人。这个过程沿着圆圈一直进行直到最终只剩下一个人留下这个人就可以继续活着。 问题是给定了n和k一开始要站在什么地方才能避免被处决 问题是以弗拉维奥·约瑟夫斯命名的它是1世纪的一名犹太历史学家。他在自己的日记中写道他和他的40个战友被罗马军队包围在洞中。他们讨论是自杀还是被俘最终决定自杀并以抽签的方式决定谁杀掉谁。约瑟夫斯和另外一个人是最后两个留下的人。约瑟夫斯说服了那个人他们将向罗马军队投降不再自杀。约瑟夫斯把他的存活归因于运气或天意他不知道是哪一个。 解法 1.用循环单链表模拟整个过程时间复杂度是O(n*m) 2.如果只是想求得最后剩下的人则可以用数学推导的方式得出公式。 要模拟整个游戏过程不仅程序写起来比较烦而且时间复杂度高达O(nm)当nm非常大(例如上百万上千万)的时候几乎是没有办法在短时间内出结果的。我们注意到原问题仅仅是要求出最后的胜利者的序号而不是要读者模拟整个过程。因此如果要追求效率就要打破常规实施一点数学策略。 为了讨论方便先把问题稍微改变一下并不影响原意问题描述n个人编号0~(n-1))从0开始报数报到(m-1)的退出剩下的人继续从0开始报数。求胜利者的编号。我们知道第一个人(编号一定是m%n-1) 出列之后剩下的n-1个人组成了一个新的约瑟夫环以编号为km%n的人开始: k k1 k2 ... n-2, n-1, 0, 1, 2, ... k-2并且从k开始报0。现在我们把他们的编号做一下转换k -- 0k1 -- 1k2 -- 2......k-2 -- n-2k-1 -- n-1变换后就完完全全成为了(n-1)个人报数的子问题假如我们知道这个子问题的解例如x是最终的胜利者那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗变回去的公式很简单相信大家都可以推出来x(xk)%n如何知道(n-1)个人报数的问题的解对只要知道(n-2)个人的解就行了。(n-2)个人的解呢当然是先求(n-3)的情况 ---- 这显然就是一个倒推问题好了思路出来了下面写递推公式令f[i]表示i个人玩游戏报m退出最后胜利者的编号最后的结果自然是f[n]递推公式f[1]0;f[i](f[i-1]m)%i; (i1)有了这个公式我们要做的就是从1-n顺序算出f[i]的数值最后结果是f[n]。因为实际生活中编号总是从1开始我们输出f[n]1由于是逐级递推不需要保存每个f[i]程序也是异常简单 #include stdio.h
int main()
{int n, m, i, s 0;printf (N M );scanf(%d%d, n, m);for (i 2; i n; i){s (s m) % i;}printf (\nThe winner is %d\n, s1);
} 这个算法的时间复杂度为O(n)相对于模拟算法已经有了很大的提高。算nm等于一百万一千万的情况不是问题了。可见适当地运用数学策略不仅可以让编程变得简单而且往往会成倍地提高算法执行效率。相比之下解法二的优越性不言而喻同时说明数学确实很重要。 组合数学置换计算机科学基础理论数学问题 http://blog.csdn.net/wuzhekai1985/article/details/6628491 http://www.cnblogs.com/EricYang/archive/2009/09/04/1560478.html转载于:https://www.cnblogs.com/kimsimple/p/7468330.html