如何利用约瑟夫环来保护你与你的朋友

Posted hardy-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用约瑟夫环来保护你与你的朋友相关的知识,希望对你有一定的参考价值。

题目描述:

据说著名犹太历史学家 Josephus(约瑟夫)有过以下的故事:在罗马人占领乔塔帕特后, 39 个犹太人与 Josephus 及他的朋友躲到一个洞中,39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41 个人排成一个圆圈,由第 1 个人开始报数,报数每报到第 3 个人该人就必须自杀,然后再由下一个人从 1 开始重新报数,直到所有人都自杀身亡为止。
然而 Josephus 和他的朋友并不想遵从,Josephus 要他的朋友先假装遵从,他将朋友与自己安排在第 16 个与第 31 个位置,于是逃过了这场死亡游戏。
约瑟夫问题可用代数分析来求解,假设现在你与 m 个朋友不幸参与了这个游戏,你要如何保护你与你的朋友?

分析与解答:

实际上只要画两个圆圈就可以让自己与朋友免于死亡游戏,这两个圆圈中内圈是排列顺序,而外圈是自杀顺序,如下图所示。
技术图片

使用程序来求解的话,只要将阵列当作环状来处理,在阵列中由计数 1 开始,每三个数得到一个计数,直到计数到 41 为止;然后将阵列由索引 1 开始列出,就可以得知每个位置的自杀顺序,这就是约瑟夫排列。41 个人报数的约瑟夫排列如下所示(第一个开始对应每个人的站位):
14 36 1 38 15 2 24 30 3 16 34 4 25 17 5 40 31 6 18 26 7 37 19 8 35 27 9 20 32 10 41 21 11 28 39 12 22 33 13 29 23
由上述排列可知,最后一个自杀的是在第 31 个位置的人,而倒数第二个自杀的要排在第 16 个位置,之前的人都死光了,所以他们也就不知道约瑟夫与他的朋友有没有遵守游戏规则了。
实现代码如下:

define(‘N‘, 41);//参与人数
define("M", 3);//每逢3自杀
$man = array(0);
$count = 1;
$i = 0;
$pos = -1;
$alive = 2;//想要救的三个人
while ($count <= N) {
    do {
        $pos = ($pos + 1) % N;
        if (@$man[$pos] == 0)
            $i++;
        if ($i == M) {
            $i = 0;
            break;
        }
    } while (1);
    $man[$pos] = $count;
    $count++;
}

arsort($man);

$arr = array_slice($man, 0, $alive, true);

for ($i = 0; $i < N; $i++) {
    echo "" . $man[$i] . ‘-‘;
}

程序的运行结果为

14-36-1-38-15-2-24-30-3-16-34-4-25-17-5-40-31-6-18-26-7-37-19-8-35-27-9-20-32-10-41-21-11-28-39-12-22-33-13-29-23






以上是关于如何利用约瑟夫环来保护你与你的朋友的主要内容,如果未能解决你的问题,请参考以下文章

能走多远,取决于你与谁同行

如何使用React.lazy和Suspense进行组件延迟加载

看小朋友做游戏顿时解决了约瑟夫问题

掌握主动权

岁月痕迹

数据结构与算法: 约瑟夫问题(丢手绢)