(算法)约瑟夫环问题

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后出列的人(编号)即为原问题的解。
思路:假如有7个人,围成一圈,从某个人开始编号0到6,从编号为0的人开始数1到3,数到3的人出列,下一个人又从1开始数到3,数到3的人又出列,知道最后一个人为止,我们写一下过程,用编号来表示:
一:0、1、2、3、4、5、6(数到3,编号2出列,然后从编号3开始);
二:3、4、5、6、0、1(数到3,编号5出列,然后从编号6开始);
三:6、0、1、3、4(数到3,编号1出列,然后从编号3开始);
四:3、4、6、0(数到3,编号6出列,然后从编号0开始);
五:0、3、4(数到3,编号4出列,然后从编号0开始);
六:0、3(数到3,编号0出列,然后从编号3开始);
七:3(显然最后是编号3出列)。
上面的思路分析重要的一点是这些人是围成一圈的,即编号是循环来数的,从哪个编号开始是无关重要的,取决于你从哪个人开始编号,从哪个编号开始数,博主上面写的这七个编号写成一排,每一趟的起始点可能不一样,符合循环次序就好,这只是便于分析,我们可以用一个数组来存这些编号,然后通过操作数组来得到我们想要的结果,上面每一趟的变化我们可以用简单的c代码来表示(我们使用了两个数组:int a[7],int b[7],一开始初始化它们的内容相同,数组a的循环内容变化通过b[(i + 3) % n]来操作):

while(n > 1)
    { for(i = 0;i < n - 1;i++) { a[i] = b[(i + 3) % n]; }
        for(i = 0;i < n - 1;i++)
        { b[i] = a[i]; }
        n--;
    }

我们推广到一般情形,它有n个人,围成一圈,从0到n-1编号,并从编号k开始数1到m,数到m的人出列,下一个人又从1开始数,数到m的人又出列,直到最后一个人出列,每一趟变化用c代码表示为:

while(n > 1)
    { for(i = 0;i < n - 1;i++) { a[(i + k) % (n - 1)] = b[(i + k + m) % n]; }
        for(i = 0;i < n - 1;i++)
        { b[i] = a[i]; }
        n--;
    }

下面就是博主用c语言写的完整程序:

#include<stdio.h>
int fun(int a[],int b[],int n,int m,int k);
int main(void)
{
    int i,n,m,k;
    int a[10],b[10];
    printf("请您输入总共的人数(n):");
    scanf("%d",&n);
    printf("让这%d个人围成一圈,从0到%d来编号,。\n",n,n-1);
    printf("请您输入k的值,让%d个编号从k编号开始数:",n);
    scanf("%d",&k);
    printf("从编号%d开始,1开始数,数到m,然后去除数到m的编号,接着让下一个输入从1开始报数直到m就去除该编号,请您输入m的值:",k);
    scanf("%d",&m);
    for(i = 0;i < n;i++)
    {
        a[i] = i;
        b[i] = i;
    }
    printf("最后剩下的编号是:");
    printf("%d",fun(a,b,n,m,k));
    return 0;
}


int fun(int a[],int b[],int n,int m,int k)
{
    int i;
    while(n > 1)
    {
        for(i = 0;i < n - 1;i++)
        {
            a[(i + k) % (n - 1)] = b[(i + k + m) % n];
        }
        for(i = 0;i < n - 1;i++)
        {
            b[i] = a[i];
        }
        n--;
    }
    return a[0];
}

以上是博主的分享,谢谢各位读者的浏览!

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/xiaojinit/article/details/51066802
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞