PTA 7-28猴子选大王(C语言实现)

[题目描述]

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

[输入格式]

输入在一行中给一个正整数N(≤1000)。

[输出格式]

在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

解题思路 :

对于猴子选大王这道题,每次从1数到3,喊到数字3的猴子退出圈子,直到最后只有一只猴子为止。我的初步想法是用一个数组来解决问题,由于数组是从0开始,而我们这道题的猴子是从1编号,所以我在数组下标为0的位置放置0,这样数组下标为1的位置放置1,以此类推。可以用一个变量cnt来表示数组中元素为0的个数,当cnt小于猴子的总数时一直进行如下循环:使用变量i记录数组下标,我们希望i所对应的元素非0,同时注意i的值不能大于猴子总数;使用变量j记录从1数到3,当j大于3时置j为1,当j为3时,将数组下标为i的元素置为0,同时cnt加1。最后输出数组中的非0元素即为我们想要的结果。
还可以使用约瑟夫环一种数学方法,不过我还没有搞明白o(╥﹏╥)o

C语言代码如下:
#include <stdio.h>
int main(void){
  int n,i,a[1000],cnt,j,k;scanf("%d",&n);
  for(i=0;i<=n;i++){a[i]=i;}
  cnt=1;i=0;j=1;while(a[i]==0){i++;if(i>n)i=0;}
  while(cnt<n){
    if(j==3){a[i]=0;cnt++;}
    j++;if(j>3)j=1;
    i++;if(i>n)i=0;
    while(a[i]==0){i++;if(i>n)i=0;}}
  for(k=0;k<=n;k++){if(a[k])printf("%d",a[k]);}
  return 0;}

【也可以这样写】最近又遇到了类似的题目,重新写了一下。

# include <stdio.h>
int main()
{
    int n;
    scanf("%d", &n); // 输入猴子的数量

    int m = 3; // 变量m记录报到哪个数要退出圈子
    int s = n; // 变量s记录当前在圈内的猴子数
    int a[1005] = {0}; // 数组a记录这n个猴子是否在圈内,初始值全为0,表示n个猴子全部在圈内,出圈后应修改元素为1
    int k = 0, p = 0; // 变量k记录当前报数是多少,变量p记录当报到最后一个猴子时,反过来从前面的哪个位置开始报数
    while (s) { // 当圈内有猴子时进行循环
        while (a[p] != 0) { // 找到本次报数从第几个猴子开始报数
            ++p;
        }
        for (int i = p; i < n; ++i) { // 遍历数组a
            if (!a[i]) { // 如果第i+1个猴子在圈内,
                ++k; // 报数加1
                if (k == m) { // 恰好报到m
                    if (s == 1) {
                        printf("%d", i + 1); // 输出猴王的编号
                    }
                    a[i] = 1; // 修改对应元素为1
                    --s; // 圈内的猴子数要相应减1
                    k = 0; // 报数归零,从0开始
                }
            }
        }
    }
    return 0;
}

也可以这样写。

#include <stdio.h>
#define N 80
int main(void)
{
    int n;
    printf("Enter n:");
    scanf("%d", &n);
    int a[N] = {0};
    int cnt = n;
    int k = 0, i = 0;
    while (1) {
        if (a[i] == 0) {
            k++;
            if (k == 3) {
                a[i] = !a[i];
                cnt--;
                if (cnt == 1) {
                    for (int p=0; p<n; p++) {
                        if (a[p] == 0) {
                            printf("Last No is %d", p+1);
                        }
                    }
                    break;
                }
                k = 0;
            }
        }
        i++;
        if (i == n) {
            i = 0;
        }
    } 
    return 0;
}
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值