M个人的圈,从某一个起点开始数N个数,这个位置上的人离开,从下一个人开始继续数N个数,最后离开的人是谁?
从下图看好比两个圆,大小其实可以变化,外圆有一个标记点,与内圈贴身滚动时回有一个标记点重合的瞬间,那一刻内圆的该点标记并递增计数,此时外圆继续滚动直到下一次的标记。理论上最后所有点会被标记。此题用这种数学模型分析后就好求解了。
请输入总人数(也即内圆周长,当然我们假设都是整数)
10
请输入数数基数(也即外圆周长,同样,当然我们假设都是整数)
3
最初的位置-约瑟夫环位置
[1-6][2-4][3-1][4-10][5-8][6-2][7-5][8-7][9-3][10-9]
package com.fulei_master.haliluya.oj;
import java.util.Scanner;
public class theYeSeFuLoop {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("请输入总人数(也即内圆周长,当然我们假设都是整数)");
int M = s.nextInt();
System.out.println("请输入数数基数(也即外圆周长,同样,当然我们假设都是整数)");
int N = s.nextInt();
// if(M<0 ||M>100){
// M = 50;//为了显示输出,限制下范围
// }
// if(N<0 ||N>M){
// N = 8;//为了显示输出,限制下范围
// }
//
int[] man = new int[M];
int count = 1;//计数器
int i = 0;
int pos = -1;//外圆与内圆当前贴身的下标
//初始化
initialArr(man,0);
//开始给每个人标记在给定的M N值下,该人是第几个被标记的
while(count<=M){
//外圆滚动过程
do{
pos= (pos+1)%M; //把数组前移过程转化为环状,外圆的当前贴身位置前移
if(man[pos] ==0){ //如果该人已经被选出来 ,标记过号码 ,则跳过
i++;
}
if(i ==N){ //小圆转了一圈,肯定有新的人被挑选出来,古跳出循环
i =0;
break;
}
}while(true);
man[pos] = count; //最后的位置就是出来的人
count++;
}
printYeSeFuLoop(man);
}
private static void printYeSeFuLoop(int[] arr) {
int temp = 0;
System.out.println("最初的位置-约瑟夫环位置");
for(int i = 0 ; i<arr.length ;i++){
temp = i+1;
System.out.print("[" + temp + "-" + arr[i] + "]");
if(i!=0 && i%10 ==0){
System.out.println();
}
}
}
/**
* 初始化整形数组
* @param arr
* @param value
*/
private static void initialArr(int[] arr,int value) {
for(int j = 0;j<arr.length ;j++){
arr[j] =value;
}
}
}