求围圈问题的详细算法

本文详细介绍了三种不同算法解决围圈问题的过程,并通过C语言实现,输入人数和倍数值,输出最后剩余人员的编号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我用三种不同的算法来做的:

/*求围圈问题的详细算法和程序*/
/*n人围成一圈,编号为1,2,3,……,17,从1开始报数,报到m的倍数的人离开,
一直下去,直到最后剩下1人,求此人的编号  */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 int n, m;  
 int* a;    /* 用于存储“那些人” */
 int i, j, s; 
 
 printf("请输入多少个人:/n");
   scanf("%d",&n);
   printf("请输入是哪个数字的倍数:/n");
   scanf("%d",&m);

   a = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */
   
   if (a == NULL)    /* 并非一定分配成功的 */
   {
      printf("空间不足,程序退出。/n");
      return 1;
   }
   
   for (i = 0; i < n; i++)
   {
      a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */
   }
 i = 0;   //从下标为 i%n 的元素开始数数
 j = 0;   //记录已经退出的元素的个数
 s = n;   //记录尚未退出的元素的个数
 while(s > 1)
   {
  if(a[i%n] != 0) //如果元素值不为0,则表示其尚未退出
  {
   if((i+1-j)%m == 0) //判断当前报数(i+1-j)是否为m的倍数,(-j)表示跳过j个元素
   { 
    printf("第%d号出列/n",a[i%n]);    /* 把这个家伙打印出来 */
    a[i%n] = 0;   //已经退出的元素赋值为0
    s--;    //退出一个元素
   }
  }
  else   //如果元素值为0,则表示其已经退出
   j++; //此时i值仍然会累加,但我们记下这个已经退出的元素 ,以便报数时跳过它  
  i++;
 }
 
 for(i=0; i<n; i++)
  if(a[i] != 0)
    printf("最后一个是:%d/n",a[i]);
    
 free(a);    /* 记得要释放申请的空间 */
 system("pause");
   return 0;                
}

/*求围圈问题的详细算法和程序*/
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int* arr;    /* 用于存储“那些人” */
    int n;        /* “那些人”的总数 */
    int s;        /* 开始的编号 */
    int m;        /* 间隔多少个人出列一个 */
    int i,j;
   
    printf("请输入多少个人:/n");
    scanf("%d",&n);
   
    printf("请输入开始的序号:/n");
    scanf("%d",&s);
   
    printf("请输入间隔的人数:/n");
    scanf("%d",&m);
   
    arr = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */
   
    if (arr == NULL)    /* 并非一定分配成功的 */
    {
        printf("空间不足,程序退出。/n");
        return 1;
    }
   
    for (i = 0;i < n;i++)
    {
        arr[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */
    }
   
    printf("出列顺序:/n");
   
    j = s + m - 2;    /* 这是第一个要出列的人的下标 */
   
    while (n > 1)    /* 当队列中还有不止一个人的时候,要就进行出列的动作 */
    {
        printf("%d/n",arr[j]);    /* 把这个家伙打印出来 */
       
        /* 这个家伙走了以后,后面的人应该依次顶上来 */
        for (i = j;i < n - 1;i++)
        {
            arr[i] = arr[i + 1];
        }
        n--;    /* 并且整个队列的人少了一个,也就是长度要减掉一 */
        /* 这是下一个要出列的人 */
        j = (j + m - 1) % n;
    }
   
    /* 现在只有一个人了,就是arr[0] */
    printf("最后一个是:%d/n",arr[0]);
   
    free(arr);    /* 记得要释放申请的空间 */   
  system("pause");
    return 0;
}

/*求围圈问题的详细算法和程序*/
/*n人围成一圈,编号为1,2,3,……,17,从1开始报数,报到m的倍数的人离开,
一直下去,直到最后剩下1人,求此人的编号  */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 int n, m;  
 int* a;    /* 用于存储“那些人” */
 int i, j, s; 
 
 printf("请输入多少个人:/n");
   scanf("%d",&n);
   printf("请输入是哪个数字的倍数:/n");
   scanf("%d",&m);

   a = (int*)(malloc(sizeof(int) * n));    /* 申请一个数组,以存储“那些人” */
   
   if (a == NULL)    /* 并非一定分配成功的 */
   {
      printf("空间不足,程序退出。/n");
      return 1;
   }
   
   for (i = 0; i < n; i++)
   {
      a[i] = i + 1;    /* 填空数组,编号是下标加一,注意C语言中的数组下标从0开始 */
   }
 i = 0;   
 j = 0;   //报数
 s = n;   //记录尚未退出的元素的个数
 while(s > 1)
   {
  if(a[i%n] != 0) //如果元素值不为0,则表示其尚未退出
  {
   j++;
   if(j%m == 0) //判断当前报数是否为m的倍数
   { 
    printf("第%d号出列/n",a[i%n]);    /* 把这个家伙打印出来 */
    a[i%n] = 0;   //已经退出的元素赋值为0
    s--;    //退出一个元素
   }
  } 
  i++;
 }
 
 for(i=0; i<n; i++)
  if(a[i] != 0)
    printf("最后一个是:%d/n",a[i]);
    
 free(a);    /* 记得要释放申请的空间 */  
 system("pause");
   return 0;                
}

转载于:https://www.cnblogs.com/carekee/articles/2569773.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值