博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
约瑟夫环问题详解 (c++)
阅读量:5022 次
发布时间:2019-06-12

本文共 3286 字,大约阅读时间需要 10 分钟。

 

问题描述:

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

 


 

历史背景:

Wikipedia: 这个问题是以命名的,它是的一名犹太历史学家。

他在自己的日记中写道,他和他的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!"<

 

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

int Joseph(int m,int k,int i){    if(m<=0||k<=0||m

 

程序运行结果如下:

int main(){       cout<<"递归方法一"<

 

 结果:

 

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

 

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

 

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"<
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<
data<
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"<
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<<"循环列表"<

 

 

转载于:https://www.cnblogs.com/daimingming/p/3242406.html

你可能感兴趣的文章
【转】 mysql反引号的使用(防冲突)
查看>>
邮件中的样式问题
查看>>
AJAX 状态值与状态码详解
查看>>
php面向对象编程(oop)基础知识示例解释
查看>>
1.在数组中找到与给定总和的配对
查看>>
树的子结构
查看>>
关于根据Build Platform或者OS 加载x86或者x64 dll的问题
查看>>
程序员高效开发的几个技巧
查看>>
js-权威指南学习笔记19.2
查看>>
hexo 搭建博客
查看>>
关于 UIWebView 几个高级用法
查看>>
maven创建的项目中无法创建src/main/java 解决方案
查看>>
华为软件开发云测评报告二:代码检查
查看>>
集合1
查看>>
js 原生 ajax
查看>>
关键词 virtual
查看>>
建造者模式(屌丝专用)
查看>>
UVALive 4730 Kingdom +段树和支票托收
查看>>
[APIO2010]特别行动队
查看>>
[SCOI2016]幸运数字
查看>>