1、描述
约瑟夫环(约瑟夫问题)是一个数学的应用问题:
已知n个人(以编号1,2,3....n分别表示)围坐在一张圆桌周围。
从编号为k的人开始报数,数到m的那个人出圈;他的下一个人又从1开始报数,数到m的那个人又出圈;依次规律重复下去,直到剩余最后一个胜利者。
例如:有10个人围成一圈进行此游戏,每个人编号为1-10。若规定数到3的人出圈。则游戏过程如下:
(1) 开始报数,第一个数到3的人为3号,则3号出圈
1,2,【3】,4,5,6,7,8,9,10
(2) 从4号重新从1开始计数,则接下来数到3的人为6号,6号出圈
1,2,【3】,4,5,【6】,7,8,9,10
(3) 从7号重新从1开始计数,则接下来数到3的人为9号,则9号出圈
1,2,【3】,4,5,【6】,7,8,【9】,10
(4) 从10重新从1开始计数,由于10个人称环形结构,则接下来数到3的人为2号,2号出圈
1,【2】,【3】,4,5,【6】,7,8,【9】,10
(5) 从4号重新从1开始计数,则接下来数到3的人为7号,7号出圈
1,【2】,【3】,4,5,【6】,【7】,8,【9】,10
(6) 从8号重新从1开始计数,则接下来数到3的人为1号,1号出圈
【1】,【2】,【3】,4,5,【6】,【7】,8,【9】,10
(7) 从4号重新从1开始计数,则接下来数到3的人为8号,8号出圈
【1】,【2】,【3】,4,5,【6】,【7】,【8】,【9】,10
(8) 从10重新从1开始计数,则接下来数到3的人为5号,5号出圈
【1】,【2】,【3】,4,【5】,【6】,【7】,【8】,【9】,10
(9) 从10重新从1开始计数,则接下来数到3的人为10,10号出圈
【1】,【2】,【3】,4,【5】,【6】,【7】,【8】,【9】,【10】
(10) 最终剩余4号,4号为胜利者
2 求解
2.1 数组求解-解题思想
用数组求解的基本思想就是用一个数组去标识这n个人的状态,默认全为1,也就是都在圈子内。
当数到m的人出圈之后,标识置为0(就是出圈了),同时报数器清0,下一个要从1开始。
在每次报数之前要判断他是否在圈子内(也就是他的标识是否为1),如果在圈子里面才会继续报数。定义一个变量记录出圈的人数,出圈 的人数等于n-1时,则游戏结束。
public function joseph($n, $m) {
$flag = [];
for($i = 1; $i <= $n; $i++) {
$flag[$i] = 1;
}
// 计数器
$num = 0;
// 统计出圈的次数
$count = 0;
while($count < $n - 1) {
for($i = 1; $i <=$n; $i++) {
if($flag[$i] == 1) {
$num++;
if($num == $m) {
$num = 0;
$count++;
$flag[$i] = 0;
}
if($count == $n - 1) {
break;
}
}
}
}
for($i = 1; $i <= $n; $i++) {
if($flag[$i] == 1) {
echo "The last one is:".$i;
}
}
}