约瑟夫问题(数组方法解决,适用于人数较少的情况)

约瑟夫问题

题目描述
有M个人,其编号分别为1-M。这M个人按顺序排成一个圈。现在给定一个数N,从第一个人开始依次报数,数到N的人出列,然后又从下一个人开始又从1开始依次报数,数到N的人又出列...如此循环,直到最后一个人出列为止。
输入
输入只有一行,包括2个整数M(8 <= M <= 15 ),N( 5 <= N <= 32767 )。之间用一个空格分开。
输出
输出M行,每行一个整数。
***样例***
输入

8 5

输出

5
2
8
7
1
4
6
3

代码如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int i,j,k,m,n,a[20];
    scanf("%d%d",&m,&n);
    for(i=1;i<=m;i++)
    {
     a[i]=i;//每一个元素对应一个位置
 }
 k=1;
 do{
  k=(k+n-1)%m;//因为每一次都要从自身位置开始查起,所以要进行减1操作。
  if(k==0)//因为当其为0时说明了该位置是人数的整数倍,所以要输出最后一个
  printf("%d\n",a[m]),
  k++;//是因为没有0这个位置,当其为0时说明其在最后一个位置,所以下一次查的时候需要从1开始,故进行加1操作
  else
  {
   printf("%d\n",a[k]);
   for(i=k;i<m;i++)
   {
    a[i]=a[i+1];//当k位置的人出列后,把后面的元素都要前进一位。
   } 
  }
 }while(--m);//先减1在判断,直到人数为0为止。
    return 0;
}
好的,关于约瑟夫问题,我可以给你提供一个基于数组的 C 语言解决方案。具体思路是:先创建一个长度为 n 的数组,表示有 n 个人参与游戏,然后依次将这些人编号为 1 到 n。接着,从编号为 k 的人开始报数,每报到 m 就将该人从数组中删除,直到数组中只剩下一个人为止。最后剩下的那个人即为胜者。 下面是代码实现: ```c #include <stdio.h> int main() { int n, m, k; printf("请输入参与游戏的人数 n:"); scanf("%d", &n); printf("请输入报数的上限 m:"); scanf("%d", &m); printf("请输入从第几个人开始报数 k:"); scanf("%d", &k); int a[n]; // 创建长度为 n 的数组 for (int i = 0; i < n; i++) { a[i] = i + 1; // 将每个人编号存入数组中 } int count = 0; // 记录已经报数人数 int index = k - 1; // 记录当前报数的人在数组中的下标 while (n > 1) { if (a[index] != 0) { // 如果当前报数的人还在数组中 count++; // 已经报数人数加一 if (count == m) { // 如果已经报数到 m a[index] = 0; // 将该人从数组中删除 count = 0; // 已经报数人数清零 n--; // 参与游戏的人数减一 } } index++; // 下一个报数 if (index == n) { // 如果已经报数最后一个人 index = 0; // 从第一个人重新开始报数 } } for (int i = 0; i < n; i++) { if (a[i] != 0) { // 找到最后剩下的那个人 printf("胜者的编号是:%d\n", a[i]); break; } } return 0; } ``` 你可以根据需要修改代码中的变量名和注释,以便更好地理解和使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值