A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© adalvik 中级黑马   /  2015-4-18 20:10  /  822 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 adalvik 于 2015-4-18 20:12 编辑

有100个人围成一个圈,从1开始报数,报到14的这个人就要退出。然后其他人重新开始,从1报数,到14退出。问:最后剩下的是100人中的第几个人?

这个问题是一哥们认为很难的问题,可能这哥们很少接触数据结构吧..其实这就是一个约瑟夫环算法的问题

先引入一个典故

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏...

是不是感觉这个问题 和 这哥们提的问题一样~

那么看代码吧


  1. import java.util.Scanner;


  2. public class demo09 {

  3.         static final int Num=100;                                                 //总人数
  4.         static final int KillMan=14;                                                 //数到多少退出

  5.         static void Josephus(int alive)                                        //约瑟夫环算法
  6.         {
  7.             int[] man=new int[Num];
  8.             int count=1;
  9.             int i=0,pos=-1;

  10.             while(count<=Num)
  11.             {
  12.                 do{
  13.                     pos=(pos+1) % Num;                  //环处理
  14.                     if(man[pos]==0)
  15.                         i++;
  16.                     if(i==KillMan)                                 //该人退出
  17.                     {
  18.                         i=0;
  19.                         break;
  20.                     }
  21.                 }while(true);
  22.                 man[pos]=count;
  23.                         System.out.printf("第%2d个人退出!约瑟夫环编号为%2d",pos+1,man[pos]);
  24.                         if(count%2==1)
  25.                         {
  26.                                 System.out.printf(" -> ");
  27.                         }
  28.                         else
  29.                         {
  30.                                 System.out.printf(" ->\n");                                //输出换行
  31.                         }
  32.                 count++;
  33.             }
  34.             System.out.printf("\n");
  35.             System.out.printf("这%d需要存活的人初始位置应排在以下序号:\n",alive);
  36.             alive=Num-alive;
  37.             for(i=0;i<Num;i++)
  38.                 {
  39.                 if(man[i]>alive)
  40.                         {
  41.                     System.out.printf("初始编号:%d,约瑟夫环编号:%d\n",i+1,man[i]);
  42.                         }
  43.                 }
  44.             System.out.printf("\n");
  45.         }
  46.         public static void main(String[] args)
  47.         {
  48.                 int alive;
  49.                 Scanner input=new Scanner(System.in);
  50.             System.out.printf("约瑟夫环问题求解!\n");
  51.                 System.out.printf("输入需要留存的人的数量:");               
  52.             alive=input.nextInt();                        //输入留存的人的数量
  53.                 Josephus(alive);

  54.         }

  55. }
复制代码





6 个回复

倒序浏览
这个算法有什么用的?
回复 使用道具 举报
:handshake:handshake
回复 使用道具 举报
研究研究......
回复 使用道具 举报
  好强大~~~~~~~~~~~~~~~~~
回复 使用道具 举报
本帖最后由 rick1991chen 于 2015-4-18 22:07 编辑

能给点注释就好了,看的有点混乱
回复 使用道具 举报
几行搞定;P
  1.     public int josephusRing(int n, int m) {
  2.         int k = 1;
  3.         for (int i = 2; i <= n; i++) {
  4.             k = (k + m % i) > i ? (k + m % i) % i : k + m % i;
  5.         }
  6.        return k;
  7.     }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马