约瑟夫环问题描述:
编号为1-N的N个人按顺时针方向围坐成一圈,从第S个人开始报数(从1报起),报数为M的人出圈,再从他的顺时针方向的下一个人重新开始报数,如此下去,直至所有人出圈为止,给出N个人的出去顺序
算法:
1、设置一个boolean数组out,元素out[i]标记编号为i的人是否已经出圈
2、从编号为S 的人开始,若为报数至M,则继续寻找下一出圈标记为false的 人
3、输出报数为M的人的编号,并修改其对应的出圈标记为true
4、若输出人数未达到M,则继续寻找下一出圈标记为false的人并重新报数,否则结束
源代码:
package ch4_2;
public class JosephRing {
public static void main(String[] args) {
// 总人数
final int N = 13;
// 从第S个人开始报数
final int S = 3;
// 报数为M的人出圈
final int M = 5;
// 统一下标与人的标号(自然计数)
boolean[] out = new boolean[N + 1];
// 初始化数组
for (int i = 1; i <= N; i++) {
// 报数前所有人都未出圈
out[i] = false;
}
// 存放下次开始报数的人的编号
int i = S;
// 已出圈的人
int n = 0;
// 报数为count的人
int count;
System.out.println("出圈顺序:");
// 仍有人在圈内
while (n < N) {
// 出圈后重新计数
count = 0;
// 未报数至M
while (count < M) {
// 报数的人未出圈
if (out[i] == false) {
// 报数
count++;
}
// 未报数至M(上面的if语句可能修改了count)
if (count < M) {
// 求下一个的编号(到达N+1则回到第1个人)
i = (i + 1 > N ? 1 : i + 1);
}
}
// 内层while结束,编号为i的人出圈
System.out.println(i + " ");
// 标记出圈的人
out[i] = true;
// 又有一人出圈
n++;
}
}
}