约瑟夫问题的递归公式

1,2....N  f(N) = ?

1. N = 3k

   1,2,4,5..............3k-2 3k-1 剩下 2 * N / 3个。r = f(2k)

   则f(N) = ((r-1)/2) * 3 + 2 - r%2

2. N = 3k + 1, r = f(2k+1)
   则 if r = 1
    f(N) = 3k+1;
      else
        f(N) = ((r-2)/2) * 3 + 2 - (r-1)%2

3. N = 3k+2,r = f(2k+2)
    if r = 1
       f(N) = 3k+1
    else if r = 2
       f(N) = 3k+2
    else

       f(N) = ((r-3)/2) * 3 +2 - (r-2)%2

 1 
 2  #include  < iostream >
 3  using   namespace  std;
 4 
 5  int  f( int  n)
 6  {
 7       if (n  ==   2 )
 8           return   2 ;
 9       int  k  =  n  /   3 ;
10       if (n  %   3   ==   0 )
11      {
12           int  r  =  f( 2 * k);
13           return  ((r  -   1 ) / 2 *   3   +   2   -  r % 2 ;
14      } else   if (n % 3   ==   1 )
15      {
16           int  r  =  f( 2 * k + 1 );
17           if  (r  ==   1 )
18               return   3 * k + 1 ;
19           return  ((r  -   2 ) / 2 *   3   +   2   -  (r - 1 ) % 2 ;
20      }
21       else {
22           int  r  =  f( 2 * k + 2 );
23           if  (r  ==   1 )
24          {
25               return   3 * k + 1 ;
26          }
27           if  (r  ==   2 )
28          {
29               return   3 * k + 2 ;
30          }
31           return  ((r  -   3 ) / 2 *   3   +   2   -  (r - 2 ) % 2 ;
32      }
33  }
34  int  main()
35  {
36      cout  <<  f( 17 <<  endl;
37       return   0 ;
38  }


 

转载于:https://www.cnblogs.com/speedmancs/archive/2010/10/14/1851751.html

### 约瑟夫问题递归解决方案 #### 一、问题描述 约瑟夫问题是计算机科学中的经典问题之一。给定n个人围成一圈并依次编号为1到n,从第一个人开始报数,每报到m的人就出局,剩下的人继续重新从1开始报数,直到最后只剩下一个人为止。 #### 二、递归法详解 ##### (1)问题分析 为了简化计算过程,在每次有人被淘汰之后可以认为剩下的部分形成了一个新的更短的序列来重复相同的操作。通过观察发现当只有两个人时可以直接得出结论谁会获胜;而如果人数超过两人,则可以通过减去已经移除掉的那个位置再做相应的调整得到新的起始点来进行下一轮迭代[^1]。 ##### (2)代码实现 下面给出了解决该问题的一个简单版本——基于递推公式的非尾递归方式: ```c #include <stdio.h> // 计算最终幸存者的索引(0-based) int josephus(int n, int m) { if (n == 1) return 0; else return (josephus(n - 1, m) + m) % n; // 当前轮次的安全位由上一轮的结果决定 } int main() { int n = 7; // 总共多少人 int m = 3; // 数到几淘汰 printf("The survivor is at position: %d\n", josephus(n, m)+1); // 输出结果转换回1-base表示形式 } ``` 这段程序利用了数学归纳的思想,即对于任意规模较小的情况都已知解的情况下求解更大规模的问题。这里`josephus()` 函数接收两个参数 `n` 和 `m`, 表示总共有 n 名参与者以及每隔 m 个就会被踢出去一位成员。函数内部采用了简单的条件判断语句区分基本情况与一般情况,并且使用模运算实现了环绕效果以适应圆圈特性。 ##### (3)运行结果 上述代码片段执行后将会输出最后一个存活者的位置(按照人类习惯计数的方式),例如输入7名玩家每隔第三个被淘汰则显示“The survivor is at position: 4”。 ##### (4)算法解析 此方法的时间复杂度主要取决于递归调用次数O(n),因为每一次都会减少一名参赛选手直至只剩余一人。空间消耗方面由于栈帧的存在同样也是线性的 O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值