PHP实现 约瑟夫报数问题

有10个人报数,从1,2,3开始报,但有人喊道3时,退出。然后从退出的后面一个人开始重新报数,数到3的人又退出,直到剩下最后一个人。

    $inCir = array();

    // 如果有10个人, 每个人都在圆圈内
    for ($i=1; $i<=10; $i++) {
        $inCir[$i] = 1;
    }

    $countPeople = count($inCir);

    // 开始报数
    $callNo = 0;

    // 从第一个人开始报数
    $peopleNo = 1;

    // 出去的人人数
    $outCir = 0;

    // 当只有一个人的时候,停止循环
    while($outCir !== $countPeople - 1) {

        // 如果此人么有出去,则继续报号
        if ($inCir[$peopleNo] == 1) {
            $callNo++ ;
        }

        //如果此人报数为3 则设置为已经出去
        if ($callNo === 3) {
            $inCir[$peopleNo] = 0;
            $outCir++;
            // 重新开始报号
            $callNo = 0;
        }

        // 该下一个人报号
        $peopleNo = $peopleNo + 1;

        // 如果到第10个人,则有重新回到第一个人
        if ($peopleNo > $countPeople) {
            $peopleNo = 1;
        }
    }

    for ($i=1; $i<=$countPeople; $i++) {
        if ($inCir[$i] == 1) {
            echo $inCir[$i];
        }
    }

在做这个题目遇到的问题:

初始化报数从1开始,$callNo=1 因为我想到的是从1开始报数。 这样做有一个问题是,第二个人就报3了,事实上应该是第三个人报3,这是为什么呢?

因为,如果报数从1开始,检测第一个人是否被踢出去,自然没有被踢出去出去,报数变成2。 接下来,就是轮到第二个人,检测第二个人也没有出去,然后 注意,这个时候,报数变成3了,最终判定这个人要被踢出去,但此时这个人还是第二个人,报数增加1之后,才轮到下一人!!

这个问题,就是报数报早了,所以 必须从0开始报。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用函数实现约瑟夫报数的方法如下: 首先,需要定义一个函数来解决约瑟夫问题。函数名可以为Josephus_problem,参数为整数n,表示初始的人数。 在函数内部,我们需要动态分配一个长度为n的整型数组arr,用来表示每个人的生命值。初始时,将数组中的所有元素都赋***初始值为n;count用来进行报数,初始值为0。 然后,我们进行一个while循环,条件是tmp大于1,也就是还有超过一个人存活。 在循环中,我们使用for循环遍历数组arr,判断每个人的生命值是否为1。如果是1,则进行报数操作。 报数操作是将count加1,如果count等于3,则将该人的生命值赋为0,表示该人被淘汰。然后,tmp减1,count重置为0。 最后,在for循环外再次使用一个for循环遍历数组arr,找到生命值为1的人,返回其索引值,即为最后剩下的人。 如果遍历完整个数组都没有生命值为1的人,则返回-1,表示没有人存活。 最后,在main函数中调用Josephus_problem函数,并将人数作为参数传入。然后,将返回值打印出来,即为最后剩下的人的索引值。 使用函数实现约瑟夫报数的完整代码如下: #include <stdio.h> #include <stdlib.h> int Josephus_problem(int n) { int* arr = (int*)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { arr[i] = 1; } int tmp = n; // 幸存人数 int count = 0; // 报的号 while (tmp > 1) { for (int i = 0; i < n; i++) { if (arr[i] == 1) { count++; if (count == 3) { arr[i] = 0; tmp--; count = 0; } } } } for (int i = 0; i < n; i++) { if (arr[i] == 1) { return i; } } return -1; } int main() { printf("%d\n", Josephus_problem(人数 - 1)); return 0; } 其中,将代码中的人数部分替换为实际的人数即可。请注意,人数应当减去1,因为数组的索引从0开始。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C语言 (编程题:约瑟夫报数游戏)](https://blog.csdn.net/weixin_56935264/article/details/121627282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值