约瑟夫环的问题

有n个人围城一个圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号那位。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define nmax 50

int main()
{
    //i是循环变量,代表着循环到第i+1个人
    //n是总人数
    //num是这些人围成的圈,其中,num[n]到num[49]无意义
    //k是循环到的那个人报的数
    //m是已经退出了几个人
    int i,k,m,n,num[nmax],*p;
    printf("请输入总人数:");
    scanf("%d",&n);
    p=num;
    for(i=0;i<n;i++){
        *(p+i)=i+1;   //对数组中的各元素进行 1到n的赋值 ,也就是每个人的标号
    }
    i=0;
    k=0;
    m=0;
    //依次报数1,2,3,报到3的元素使之值为0,重复n-1次
    while(m<n-1){       //当退出去的人等于n-1时(即只剩一人),循环退出
            //因为有n个人,m为退出的人数,当while循环m不小于n-1时,表达式为0,退出循环,即只剩一人
        if(*(p+i)!=0)k++;    //如果这个人没有退出圈子,就报数
    //每个人报数,从1开始,k相当于每个人报的数字
        if(k==3){
            *(p+i)=0;    //因为这个人报到3,把他的值设为0,表示他已退出该圈
            k=0;         //再将k置为0.重新开始报数
            m++; }        //退出的人数加1}
         i++;             //表示指针的移动,一个一个报数
        if(i==n)          //当i==n时,表示报到了最后一个
            i=0;          //将i置0,再从第一个开始报

    }

    while(*p==0)
        p++;              //上面那个循环结束后,只有一个人留了下来,然后指针开始寻找最后剩下的一个人
//上面这句话执行完之后,p指向剩下来那一个。
    printf("%d  \n",*p);
    return 0;
}




//整个程序n个人围城的圈不发生改变,只有每次报到的那个人,它本身的标志变为0,于是在第一个循环中,if(!=0)那个语句
//可以在接下来的报数中不将等于0的人计算在内

猜你喜欢

转载自blog.csdn.net/weixin_46202527/article/details/112895770