目录

一、问题描述

二、用数组求解

三、用递归求解



一、问题描述

约瑟夫环(Josephus Circle)是一个数学的应用问题:已知 n 个人(分别用编号 0, 1, 2, …, n – 1 表示)围坐在一张圆桌周围。从编号为 0 的人开始报数,数到 m 的那个人出圈,他的下一个人又从 1 开始报数,数到 m 的那个人又出圈,依次规律重复下去,直到剩余最后一个胜利者。例如,有 10 个人围成一圈进行此游戏,每个人的编号为 0 ~ 9,规定数到 3 的人出圈,则游戏过程如下所示:

  1. 0,1,[2],3,4,5,6,7,8,9

  2. 0,1,[2],3,4,[5],6,7,8,9

  3. 0,1,[2],3,4,[5],6,7,[8],9

  4. 0,[1][2],3,4,[5],6,7,[8],9

  5. 0,[1][2],3,4,[5][6],7,[8],9

  6. [0][1][2],3,4,[5][6],7,[8],9

  7. [0][1][2],3,4,[5][6][7][8],9

  8. [0][1][2],3,[4][5][6][7][8],9

  9. [0][1][2],3,[4][5][6][7][8][9]

所以出圈的顺序是:2,5,8,1,6,0,7,4,9。最终剩下 3 号,3 号是胜利者。

二、用数组求解

#include #define N 100000// 最大数// 用一维数组 is_out 来标识这 N 个人的状态,0 表示没有出圈,1 则表示出圈了。int is_out[N] = { 0 };int main(){int n = 0;// 游戏参与的人数int m = 0;// 数到 m 时出圈scanf("%d%d", &n, &m);int count = 0;// 出圈的人数int num = 0;// 报数器,当报到数字 m 时出圈int i = 0;// 从编号为 0 的人开始报数// 一、淘汰 n - 1 个人while (count  n - 1)i = 0;}printf("\n");// 二、输出胜者的编号for (i = 0; i < n; i++){if (is_out[i] == 0)printf("The winner is %d\n", i);}return 0;}

三、用递归求解

定义递归函数:josephus(int n, int m, int i),它表示在有 n 人的圆桌中,报到数字 m,第 i 个人出圈的编号

第 1 个人出圈的编号是 (m – 1) % n,因为编号从 0 开始,且有 m n 的两种情况

当第 i 个人出圈后,剩下的 n – i 个人就组成了新的约瑟夫环

#include int josephus(int n, int m, int i){if (i == 1)return (m - 1) % n;elsereturn (m + josephus(n - 1, m, i - 1)) % n;}int main(){int n = 0;int m = 0;scanf("%d%d", &n, &m);int i = 0;// 淘汰 n - 1 个人for (i = 1; i < n; i++){printf("%d ", josephus(n, m, i));}// 输出胜利者的编号printf("\n");printf("The winner is %d\n", josephus(n, m, i));return 0;}