算法导论-->约瑟夫问题

问题描述:约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。

关于输入:每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是:

0 0

关于输出:对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号。

例子输入:

6 2

12 4

8 3

0 0

例子输出:

5

1

7

提示:所给的数据中,m 未必比 n 小!
解题思路:使用链表。


  1. #include <iostream>   
  2. #include <vector>   
  3. using namespace std;  
  4.   
  5. class JosLink;  
  6. class LinkNode;  
  7.   
  8. //定义链表结点   
  9. class LinkNode  
  10. {  
  11.     friend class JosLink;  
  12.   
  13. public:  
  14.     LinkNode(int info, LinkNode* nextValue = NULL)  
  15.     {  
  16.         data = info;  
  17.         next = nextValue;  
  18.     }  
  19.   
  20. public:  
  21.     int      data;  //用于保存结点元素的内容   
  22.     LinkNode *next; //指向后继结点的指针   
  23. };  
  24.   
  25. //定义约瑟夫链表(循环链表)   
  26. class JosList  
  27. {  
  28. public:  
  29.     //构造函数   
  30.     JosList(int n){ InitList(n); }  
  31.       
  32.     //析构函数   
  33.     ~JosList();     
  34.   
  35.     //初始化包含n个猴的链表   
  36.     bool InitList(int n);  
  37.   
  38.     //删除头节点指向的下一个节点   
  39.     bool eraseNode(LinkNode *L);  
  40.   
  41. public:  
  42.     LinkNode *head, *current, *tail;  
  43. };  
  44.   
  45. bool JosList::InitList(int n)  
  46. {  
  47.     if( n<1 ) return false;  
  48.     head = new LinkNode(1);  
  49.     if( n==1 )  
  50.     {  
  51.         head->next = head;  
  52.         return true;  
  53.     }  
  54.   
  55.     for(int i=2; i<=n; i++)  
  56.     {  
  57.         current=new LinkNode(i);  
  58.         if(i==2)  
  59.         {  
  60.             head->next = current;  
  61.             tail = current;  
  62.         }  
  63.         else  
  64.         {  
  65.             tail->next = current;  
  66.             tail = current;  
  67.         }  
  68.     }  
  69.       
  70.     current->next = head; //做成循环链表   
  71.     return true;  
  72. }  
  73.   
  74. bool JosList::eraseNode(LinkNode *L)  
  75. {  
  76.     LinkNode* current = L->next;  
  77.       
  78.     if(current==L)  
  79.         return false;  
  80.   
  81.     L->next = current->next;  
  82.   
  83.     return true;  
  84. }  
  85.   
  86. int main()  
  87. {  
  88.     int n, m;  
  89.     vector<int> output;  
  90.   
  91.   
  92.     while( cin>>n>>m && n && m )  
  93.     {  
  94.         bool flag = true;  
  95.           
  96.         JosList* jList = new JosList(n);  
  97.           
  98.         if(m==1)  
  99.             output.push_back(n);  
  100.         else  
  101.         {  
  102.             while(flag)  
  103.             {  
  104.                 for(int i = 1; i < m-1; i++)  
  105.                     jList->head = jList->head->next;  
  106.                 flag = jList->eraseNode(jList->head);  
  107.                 jList->head = jList->head->next;  
  108.             }  
  109.             output.push_back(jList->head->data);  
  110.         }  
  111.     }  
  112.   
  113.     for(vector<int>::size_type i = 0; i < output.size(); i++)  
  114.     {  
  115.         cout<<output[i]<<endl;  
  116.     }  
  117.   
  118.     system("pause");  
  119.     return 0;  
  120. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值