zoukankan      html  css  js  c++  java
  • 约瑟夫环问题的递归实现

    约瑟夫环问题有很多实现方法,迭代啦,递归啦。

    这里主要介绍一下递归的方法。

    假设:

    初始情况: 0, 1, 2 ......n-2, n-1 (共n个人)

     第一个人(编号一定是(m-1)%n,设之为(k-1) ) 出列之后,

    剩下的n-1个人组成了一个新的约瑟夫环(以编号为k==m%n的人开始):

     k  k+1  k+2  ... n-2, n-1, 0, 1, 2, ...,k-3, k-2 


    现在我们把他们的编号做一下转换:


    x' -> x      (x‘代表新编号,x代表原编号   k==m%n

    k     --> 0
    k+1   --> 1
    k+2   --> 2
    ...
    ...
    k-2   --> n-2
    k-1   --> n-1

    变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗!


    x ->x'?(这正是从n-1时的结果反过来推n个人时的编号!)
    0 -> k

    1 -> k+1

    2 -> k+2

    ...

    ...

    n-2 -> k-2

    变回去的公式 x'=(x+k)%n


    那么,如何知道(n-1)个人报数的问题的解?只要知道(n-2)个人的解就行了。(n-2)个人的解呢?只要知道(n-3)的情况就可以了 ---- 这显然就是一个递归问题:


    令f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果就是f[n]


    递推公式


    f[1]=0;

    f[n]=(f[n-1]+k)%n = (f[n-1] +m%n) % n = (f[n-1] + m) % n ;  (n>1)

    当然,当n==1时,直接返回0即可

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int Josephus(int n,int m){
     5     if(n>1){
     6         return (m+Josephus(n-1,m))%n;
     7     }
     8     else{
     9         return 0;
    10     }
    11 }
    12 int main()
    13 {
    14     int n,m;
    15     scanf("%d %d",&n,&m);
    16     int result=Josephus(n,m);
    17     printf("%d",result+1);
    18 
    19     return 0;
    20 }
    有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!
  • 相关阅读:
    10 种保护 Spring Boot 应用的绝佳方法
    Redis 如何分析慢查询操作?
    Spring Boot 主类及目录结构介绍
    Redis 再牛逼,也得设置密码!!
    Spring Data Redis 详解及实战一文搞定
    Spring Boot Redis Cluster 实战干货
    超详细的 Redis Cluster 官方集群搭建指南
    Redis Linux 安装运行实战全记录
    hdu 4790 Just Random (思路+分类计算+数学)
    poj 1328 Radar Installation(贪心)
  • 原文地址:https://www.cnblogs.com/Bravewtz/p/10089717.html
Copyright © 2011-2022 走看看