问题描述:

已知n个人(以编号0,2,3...n-1分别表示)围坐在一起。从编号为0的人开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列,最后一个出列的人为胜利者。求胜利者编号.


历史背景:

Wikipedia: 这个问题是以弗拉维奥·约瑟夫斯命名的,它是1世纪的一名犹太历史学家。

他在自己的日记中写道,他和他的40个战友被罗马军队包围在洞中。

他们讨论是自杀还是被俘,最终决定自杀,并以抽签的方式决定谁杀掉谁。约瑟夫斯和另外一个人是最后两个留下的人。

约瑟夫斯说服了那个人,他们将向罗马军队投降,不再自杀。约瑟夫斯把他的存活归因于运气或天意,他不知道是哪一个.

问题分析:解决该问题有两种思路,第一种:通过建立循环链表来模拟这个过程

                  第二种:通过递归方式(数学归纳将问题转化为数学问题)

由于递归方式,代码更简洁,下面首先以递归方式来解决问题

——————递归实现:

例如 对 m= 10,k=3

   0  1  2  3  4  5  6  7  8  9  (*)

     0  1  3  4  5  6  7  8  9    (* 循环下去)

转化为:       3  4  5  6  7  8  9  0  1  (* 循环下去)

    

            0  1  2  3  4  5  6  7  8

            

            m=10,k=3 去掉一个元素之后,变成了一个m=9,k=3的约瑟夫环问题

           并且有如下关系 

           3 = (0+3)%10   4 = (1+3)%10   ... 0 = (3+7)%10

         即 3 = (0+k)% m    4 =  (1+k) % m       ... 0  = (3+k) % m

          

          m =10,k =3 设约瑟夫环最后一个出列的人为 Joseph(10,3),那么存在如下关系

          Joseph(10,3) = (Joseph(9,3)+k) %m;

          ...

          Joseph(n,k) = (Joseph(n-1,k)+k) % n (n>1);

        

C++实现如下: 

递归方法一:

 1 int Joseph(int m,int k)
2 {
3 if(m<=0||k<=0)
4 {
5 cout<<"error!"<<endl;
6 return -1;
7 }else
8 {
9 if(m==1)
10 {
11 return 0;
12 }else
13 {
14 return ((Joseph(m-1,k)+k)%m);
15 }
16 }
17 }

 递归方法二:如果输出整个出队的顺序

int Joseph(int m,int k,int i)
{
if(m<=0||k<=0||m<i)
{
cout<<"error"<<endl;
return -1; }else
{
if(i==1)
{
return (m+k-1)%m;
}else
{
return ((Joseph(m-1,k,i-1)+k)%m);
}
}
}

程序运行结果如下:

int main()
{
cout<<"递归方法一"<<endl;
cout << Joseph(6,3) << endl;
cout<<"递归方法二"<<endl;
for(int i=1;i<=6;i++)
{
cout<<Joseph(6,3,i)<<endl;
}
getchar();
return 0;
}

结果:

 ——————循环链表实现:

建立节点数据结构:循环链表

struct Node
{
int data;
Node * next;
}; struct LinkedList
{
Node *pHead;
Node *pTail;
int len;
};

建立循环链表

//建立个节点
Node * GetNode(int i)
{
Node * p = (Node *)malloc(sizeof(Node));
if(p!=NULL&&i>=0)
{
p->data = i;
p->next = NULL;
return p; }else
{ cout<<"error"<<endl;
exit(-1);
return NULL;
}
} //建立链表
LinkedList* CreateLinkedList(int i)
{
Node* node = GetNode(0);
LinkedList *head = (LinkedList*)malloc(sizeof(LinkedList));
if(head == NULL)
{
cout<<"CreateLinkedList:memory error"<<endl;
exit(-1);
return NULL;
}
if(i<=0)
{
cout<<"CreateLinkedList: error"<<endl;
exit(-1);
return NULL;
} head->pHead = node;
head->pTail = node;
head->len = 1;
if(i==1)
{
node->next = node;
}else
{
Node *p = head->pHead;
for(int j=1;j<=i-1;j++)
{
Node* node = GetNode(j);
node->data = j;
p->next = node;
p=p->next;
head->len++;
}
head->pTail = p;
p->next = head->pHead;
}
return head; }

删除节点:

//删除节点
void RemoveNode(LinkedList*head,Node *deleNode)
{
Node* p = head->pHead;
cout<<deleNode->data<<endl;
if(p!=NULL){
if(head->len>1){
do
{
if(p->data==deleNode->data)
{
if(p==head->pHead)
{
head->pHead = p->next;
}
if(p==head->pTail)
{
head->pTail = p->next;
}
p->data = p->next->data;
p->next = p->next->next;
head->len--;
return; }else{
p=p->next;
}
}while(p!=head->pHead);
}else
{
cout<<"error";
exit(-1);
return;
}
}else
{
return;
}
}

约瑟夫模拟:

int Joseph(int m,int k)
{
if(m<=0||k<=0)
{
cout<<"error:input"<<endl;
return -1;
}
LinkedList* list = CreateLinkedList(m);
//Print_List(list);
Node * p = list->pHead; for(int i=1;i<=k;i++)
{
if(list->len ==1)
{
return p->data;
}
if(i==k)
{
RemoveNode(list,p);
i = 1;
}
p=p->next;
}
return 0; }

程序运行结果如下:

int _tmain(int argc, _TCHAR* argv[])
{ cout<<"循环列表"<<endl;
cout<<Joseph(6,3)<<endl;
getchar();
return 0;
}

约瑟夫环问题详解 (c++)的更多相关文章

  1. 约瑟夫环问题详解(java版)

    1 什么是约瑟夫环问题? 约瑟夫,是一个古犹太人,曾经在一次罗马叛乱中担任将军,后来战败,他和朋友及另外39个人躲在一口井里,但还是被发现了.罗马人表示只要投降就不死,约瑟夫想投降,可是其他人坚决不同 ...

  2. 【OSPF】防环机制详解

    我们在提到OSPF的时候,时常喜欢说的一句话就是,OSPF能够计算出无环的路由,那么OSPF究竟是如何规避路由环路的呢?OSPF与距离矢量路由协议不同,运行OSPF的路由器之间交互并不是路由信息,而是 ...

  3. C语言解决约瑟夫问题详解的代码

    将开发过程中比较重要的一些内容做个收藏,下面的内容是关于C语言解决约瑟夫问题详解的内容,希望能对码农有帮助. #pragma once #include<vector> class PRO ...

  4. 1-25-循环控制符break、continue和函数详解

    大纲: 1-for循环补充 1-1-for循环实战---类C格式应用 2-break.continue循环控制符 2-1实战:帮助理解break.continue作用 3-函数详解 3-1.脚本文件中 ...

  5. 详解OJ(Online Judge)中PHP代码的提交方法及要点【举例:ZOJ 1001 (A + B Problem)】

    详解OJ(Online Judge)中PHP代码的提交方法及要点 Introduction of How to submit PHP code to Online Judge Systems  Int ...

  6. C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解

    剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...

  7. Java实现 LeetCode 面试题62. 圆圈中最后剩下的数字(约瑟夫环)

    面试题62. 圆圈中最后剩下的数字 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成一个圆 ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. 详解javascript的类

    前言 生活有度,人生添寿. 原文地址:详解javascript的类 博主博客地址:Damonare的个人博客 Javascript从当初的一个"弹窗语言",一步步发展成为现在前后端 ...

随机推荐

  1. c语言学习篇二【基础语法】

    一.定义常量: 使用 #define 预处理器. 使用 const 关键字. #include <stdio.h> int main() { const int LENGTH = 10;/ ...

  2. PostgreSQL数据库结构

    PG数据存储结构分为:逻辑结构和物理存储. 一.逻辑存储结构是:内部的组织和管理数据的方式[逻辑存储结构适用于不同的操作系统和硬件平台] 二.物理存储结构是:操作系统中组织和管理数据的方式. 1.逻辑 ...

  3. 手把手教windows上安装linux虚拟机及环境配置

    目录 版本说明 安装虚拟机 典型方式安装(推荐小白,带有图形界面,助于学习,但占用空间大) 自定义方式安装(推荐老司机) 创建快照 克隆虚拟机 windows上安装linux虚拟机不管是对于新人还是老 ...

  4. 前端知识点--CSS overflow 属性

    问题:如何加滚动条? 给div 设置css 样式overflow:scroll div { width:150px; height:150px; overflow:scroll; } -------- ...

  5. ORACLE ORA-00933: SQL 命令未正确结束,

    这个错误害我花了一天时间排查,最后原来是因为结束符,这种语句不能是分号,将分号即可执行成功. MERGE INTO MO_TRADE_COUNT_DAY A USING ( SELECT MAX(fl ...

  6. 【问题记录】- 谷歌浏览器 Html生成PDF

    起因: 由于项目需要实现将网页静默打印效果,那么直接使用浏览器打印功能无法达到静默打印效果. 浏览器打印都会弹出预览界面(如下图),无法达到静默打印. 解决方案: 谷歌浏览器提供了将html直接打印成 ...

  7. JIPB | 两篇连发:华中农大黄俊斌团队报道二羟基异丁酰化调控稻曲病菌致病新机制

    水稻是我国重要的粮食作物,稻曲病是水稻三大病害之一,不仅造成稻米产量损失,更重要的是稻曲球中的稻曲菌素的毒性和致畸作用,给人畜健康带来严重威胁.病原菌对植物的侵袭是由病原菌的毒力和植物免疫系统相互作用 ...

  8. OpenGL学习笔记(六)坐标系统

    目录 一.衔接 二.概述 三.各个坐标系统 局部空间 世界空间 观察空间 裁剪空间 四.两种投影矩阵 正射投影 透视投影 五.把它们都组合到一起 六.编码实现 1. 实现卡片旋转 2. 实现正方体旋转 ...

  9. Docker小白到实战之开篇概述

    前言 "不对啊,在我这运行很正常啊",这句话小伙伴们在前几年应该听得很多:每次一到安装.部署时总有一堆问题,毕竟操作系统版本.软件环境.硬件资源.网络等因素在作怪,此时难免会导致开 ...

  10. Docker部署ELK之部署logstash7.6.0(4)

    前言: logstash 和filebeat都具有日志收集功能,filebeat更轻量,占用资源更少,但logstash 具有filter功能,能过滤分析日志.一般结构都是filebeat采集日志,然 ...