标签:分析 define live 技术 inf class array 运行 ice
据说著名犹太历史学家 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
标签:分析 define live 技术 inf class array 运行 ice
原文地址:https://www.cnblogs.com/hardy-wang/p/12968655.html