一个小笔记(3):约瑟夫环

什么是约瑟夫环?
其实百度有说
http://baike.baidu.com/view/717633.htm

以一个传说中的问题为例子,提供源代码
主要是能够通过这个问题,了解如何来操作循环链表

在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏

最后输出结果为最后一个存活的人的编号

?

?

//?约瑟夫问题(循环链表).cpp

//?Win32控制台程序

#include?"stdafx.h"

#include?<stdlib.h>

?

typedef?struct?JOSEPH_NODE

{

????int?iNum;???//?编号

????struct?JOSEPH_NODE?*?pNext;

}?JOSEPH_NODE_S;

?

//?pJosephStart结点的下一个结点就是要杀死的人,删除该结点

void?Delete_Next_Joseph(JOSEPH_NODE_S?*?pJosephStart)

{

????JOSEPH_NODE_S?*?pJose?=?pJosephStart->pNext;

????pJosephStart->pNext?=?pJose->pNext;

????free(pJose);

}

?

//?释放链表

void?Destroy_Joseph(JOSEPH_NODE_S?*?pJosephHead)

{

????while?(pJosephHead->pNext?!=?pJosephHead)

????{

????????Destroy_Joseph(pJosephHead);

????}

????free(pJosephHead);

}

?

//?初始化链表

int?Init_Joseph(int?iCount,?JOSEPH_NODE_S?**?ppJosephHead)

{

????if?(iCount?<?1)

????{

????????return?0;

}

?

????JOSEPH_NODE_S?*?pJoseNew;

????JOSEPH_NODE_S?*?pJoseCur;

????int?iSize?=?sizeof(JOSEPH_NODE_S);

pJoseNew?=?(JOSEPH_NODE_S?*)malloc(iSize);

?

????if?(pJoseNew?==?nullptr)

????{

????????return?0;

}

?

????pJoseNew->iNum?=?1;

????pJoseNew->pNext?=?pJoseNew;

????*ppJosephHead?=?pJoseNew;

pJoseCur?=?pJoseNew;

?

????//?链表添加结点

????for?(int?i?=?1;?i?<?iCount;?i++)

????{

????????pJoseNew?=?(JOSEPH_NODE_S?*)malloc(iSize);

????????if?(pJoseNew?==?nullptr)

????????{

????????????Destroy_Joseph(*ppJosephHead);

????????????return?0;

????????}

????????pJoseNew->iNum?=?i?+?1;

????????pJoseNew->pNext?=?*ppJosephHead;

????????
?

????????pJoseCur->pNext?=?pJoseNew;

????????pJoseCur?=?pJoseNew;

}

?

????return?1;

}

?

//?得到最后一个存活的人

//?iCount:总人数

//?iSkip:每隔多少个人就杀死一个人

int?GetLastNode_Joseph(int?iCount,?int?iSkip)

{

????JOSEPH_NODE_S?*?pJoseph?=?nullptr;

????JOSEPH_NODE_S?*?pJoseStart?=?nullptr;

????if?(Init_Joseph(iCount,?&pJoseph)?!=?1)

????{

????????printf("初始化失败\n");

????????return?0;

}

?

????pJoseStart?=?pJoseph;

????//?每隔0个人杀死,最后一个人存活

????if?(iSkip?==?0)

????{

????????while?(pJoseStart->pNext->pNext?!=?pJoseStart)

????????{

????????????Delete_Next_Joseph(pJoseStart);

????????}

????????printf("Final?Num:?%d\n\n",?pJoseStart->pNext->iNum);

????????free(pJoseStart->pNext);

????????free(pJoseStart);

????????return?1;

}

?

????//?每隔iSkip个人杀死一个人

????//?直到剩下1个人,剩下最后一个结点的pNext会指向自己

????while?(pJoseStart->pNext?!=?pJoseStart)

????{

????????for?(int?i?=?1;?i?<?iSkip;?i++)

????????{

????????????pJoseStart?=?pJoseStart->pNext;

????????}

????????Delete_Next_Joseph(pJoseStart);

????????pJoseStart?=?pJoseStart->pNext;

}

?

????printf("Final?Num:?%d\n\n",?pJoseStart->iNum);

free(pJoseStart);

?

????return?1;

}

?

int?main()

{

GetLastNode_Joseph(41,?2);

?

????return?0;

}

时间: 2024-08-02 02:47:51

一个小笔记(3):约瑟夫环的相关文章

猴王问题约瑟夫环

[Joseph问题描述]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. 现在我们把他们的编号做一下转换: k --> 0 k+1 --> 1 k+2 --> 2 ... ... k-2 --&

uva live 3882 And Then There Was One 约瑟夫环

// uva live 3882 And Then There Was One // // 经典约瑟夫环问题.n是规模,k是每次数的人数,m是第一个出列的人. // // 但是暴力用链表做肯定是不行的,因为 1 <= n <= 10000 , 1<= k <= 10000 // 1 <= m <= n; 虽然我知道公式是什么,但是我并不会推导,看了几乎一个下午的 // 数学推导过程,又弄了几个样例亲自动手实验一下,这样才算是有了一点明悟. // 下面来分享一下自己能力范

C++ 约瑟夫环

约瑟夫环: 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 例如:n = 9, k = 1, m = 5 [解答]出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8. 1 int main()//约瑟夫环 2 { 3 int n=9, m=5,k=2;//n是人数(编号1,2,……,x),m是出列号,k是起始人编号 4 int

php解决约瑟夫环

今天偶遇一道算法题 "约瑟夫环"是一个数学的应用问题:一群猴子排成一圈,按1,2,-,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数, 再数到第m只,在把它踢出去-,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王.要求编程模拟此过程,输入m.n, 输出最后那个大王的编号. 方法一:递归算法 1 function killMonkey($monkeys , $m , $current = 0){ 2 $number = count($mon

php通过循环链解决约瑟夫环

本想着用php写些数据结构提升一下,写到链的时候看到约瑟夫环问题,尝试用循环链写了一下 约瑟夫环: 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列 代码: <?php header("Content-type: text/html; charset=utf-8"); /** * 约瑟

UVa 133 双向约瑟夫环

背景:1_TlE:没有考虑到,当k,m很大的时候,就会用太多时间,那么我想到了: k=k%n+n;// 之所以要加n,是为了避免,k是n的倍数时,k等于0. m=m%n+n; 2_WA:经过_TLE:之后没有完善,当k不是n的倍数时就不能加n!终究来说还是没有测试所有数据,以后切题,就把所有数据保存在记事本,要全部通过,才提交!! 好多人都说这是一个双向链表的数据结构题,被我数组模拟过了,双向约瑟夫环... 思路:小紫书在这里出这道题,是想让我们锻炼自顶向下的程序框架思想,即:想建立大框架,一些

POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数)

POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数) ACM 题目地址:POJ 2886 Who Gets the Most Candies? 题意: N 个小孩围成一圈,他们被顺时针编号为 1 到 N.每个小孩手中有一个卡片,上面有一个非 0 的数字,游戏从第 K 个小孩开始,他告诉其他小孩他卡片上的数字并离开这个圈,他卡片上的数字 A 表明了下一个离开的小孩,如果 A 是大于 0 的,则下个离开的是左手边第 A 个,如果是小于 0 的, 则是

约瑟夫问题、约瑟夫环

约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环.又称"丢手绢问题".) 1问题来历编辑 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而Jos

通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环

本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然后从出局的下一个人重新开始报数,数到第 m 个人,再让他出局......,如此反复直到所有人全部出局为止. 上一篇我们通过数组.静态链表实现了约瑟夫环,具体参考: 通过例子进阶学习C++(六)你真的能写出约瑟夫环么 本文,我们进一步深入分析约瑟夫环问题,并通过c++模板库实现该问题求解,最后我们说明