由Josephus问题说开去(to be continued)

来源:互联网 发布:jav番号新域名 编辑:程序博客网 时间:2024/06/07 03:39

问题描述:
      已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。  例如:n = 9, k = 1, m = 5。




求解方法:

方法一:

求解思想:

   开始问题中有n个人,第一次数到m的倍数时,相应的人出局,游戏中的总人数变为n-1,之后有变成n-2....,于是这个问题可以从递归的思路出发。而关键点是找出人数为n和人数为n-1时的数数的位置对应关系。






方法二:   
   
求解思想:

   把这N个数放入一个数组a[ ]中,然后从a[0]开始计数,由1依次往后数,若不是m的倍数则整个数组移动,即让a[0]到a[n-1]的位置,a[0]到a[1],依次类推,若数到的数是m的倍数,则删除a数组中对应的数,同时a数组的长度减一。这样移动的目的是让为m倍数的数始终在a[0]的位置,便于删除。


求解代码:
public class Report {public static int[] movelast(int[] a){//每次报数不是3的倍数则循环的移动一次            //目的是要将被3整除的数的初始位置值移至a[0],方便删除   int temp = a[0];   for(int i = 0;i < a.length -1 ; i++){    a[i] = a[i+1];   }   a[a.length-1] = temp;   return a;       //此时a的长度无变化}public static int[] outLine(int[] a){//新数组[]b来存储报数退出后变化的数组[]a   int[] b = new int[a.length-1]; //b[]相当于存储删掉a[0]后的新数组a[]   for(int i = 0;i<b.length; i++){    b[i] = a[i+1];     //for结束后便成功的删掉了被3整除的a[0]   }   System.out.print(a[0] + " ");//每次出列的人都是a[0]   return b;   //返回值b是删除后的a的长度,然后赋给a,作最后的循环结束判断}public static void main(String[] args) {   int[] a = new int[10];   for(int i=0;i<a.length;i++){//给0-9个人编号,数组当中的值即是他们的初始位置    a[i] = i;   }   System.out.println("出队顺序:");     for(int i = 1;a.length>1;i++){//i是报数器,从1一直报下去,直至剩下最后一人结束        //随着人员的退出,数组a的元素将越来越少,直至最后仅剩一人a[0]    if(i%3 ==0){    //如果编号为3的倍数则退出     a = Report.outLine(a);    }    else{      //否则移动位置值至a[0],a[0]相当于删除值的缓冲存储区     a = Report.movelast(a);//每当有3的倍数出现则直接删掉a[0],然后继续填充    }   }   System.out.println();   System.out.println("最后剩下的是:" + a[0]);//   for(int item : a) {//    System.out.println(item);//最后a的长度为1//   }}}


0 0