李洋疯狂C语言之n个人报数,报到3的退出,最后留在场上的是原来的第几位(约瑟夫环)

今天老师布置了个题目,约瑟夫环,俗称猴子选大王。n个人报数,报到3的退出,最后留在场上的时原来的第几位

#include <stdio.h>

int main()
{
    int i, n, q, p = 0;     //计数 i ,人数 n ,报数 p ,场上人数 q
    printf ("input number");
    scanf ("%d", &n);
    q = n;
    int a[n];

    for (i = 0; i < n; i++) //将1到n输入进数组a
    {   
        a[i] = i+1;
    }

    for (i = 0; ; i++)
    {
        if (i == n)     /*当i++一直到n时,肯定有一些没被选到,比如我们输入8,第一轮是3,6被赋值0,当i=8时,继续下一轮*/
        {
            i = 0;
        }
        if (0 != a[i])      /*我们下面定义的时当循环到三时,就赋值0,所以这边等于0的不考虑在内*/
        {
            p++;
        }
        else 
            continue;
        if (0 == p%3)   //这个就是从0一直加,到三的倍数就赋值为0,从而达到我们的目的
        {
            a[i] = 0;
            q--;            //上面q=n;标明q==n,只有一个为0就减一,为下面做铺垫
        }
            if (1 == q)     //当剩下最后一个就输出
            {
            break;
            }
    }

    for (i = 0; i < n; i++) //输出最后一个人的编号
    {
        if (0 != a[i])
            printf ("spare:%d\n", a[i]);
    }
    return 0;
}

后来在网上又看到2种不同的方法,一种是用的指针

#include <stdio.h>
int main()
{  
    int i, j, k, m, n;  
    int *p;  

    printf ("input number");
    scanf ("%d", &n); 

    int num[50];
    p = num;  

    for(i = 0; i < n; i++)  
    {  
        *(p+i) = i + 1;   //以1至n为序,给每个人编号  
    }  

    i = 0;    //i为每次循环时计数变量  
    k = 0;    //k为按1 2 3报数时的计数变量  
    m = 0;    //m为退出人数  

    while(m < n-1)  //当退出人数比n-1少时(即未退出人数大于1时)执行循环体  
    {  
        if(0 != *(p+i))  
        {  
            k++;  
        }  

        if(3 == k)    //将退出人的编号置为0  
        {  
            *(p+i) = 0;  
             k = 0;  
             m++;  
        }  
        i++;  

        if(i == n)  
        {  
            i = 0;//报数到尾后i恢复为0  
        }  
    }  

    while(0 == *p)  
    {  
        p++;  
    }  

    printf ("最后一个是:%d\n", *p);

    return 0;  
}

还有个牛人的,代码很简练(装13)

#include <stdio.h>

int main() 
{ 
    int n, i, s = 0;
    int M = 3; 
    printf ("input number");
    scanf ("%d", &n); 

    for (i = 2; i <= n; ++i) 
        s = (s+M) % i; 

    printf("%d\n", s+1); 

    return 0; 
}
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值