约瑟夫问题

来源:互联网 发布:马士兵java全套百度云 编辑:程序博客网 时间:2024/05/19 08:01

        约瑟夫问题本身好像挺简单,但它的变化形式有很多,各个问题又好像都有一些不一样,实在把人弄得头晕。先看看它的原型。参考百度上这个故事的来源:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

        (多一句嘴,故事被传来传去的,肯定都变了味,依我看这个故事未必完全符合事实。)

        我们先简单一些,假设只有10个人,从第一个人开始数数,数到2的那个人就要自杀。

         1           2          3         4         5             6           7            8              9               10

          8          1           6         2        10           3           7            4              9                5       

       如上所示,第一排是10个人的序号,第二排则是他们自杀的次序。我们可以看到,第1个人排在第8位自杀,第2个人排在第1位自杀,依此类推。那么这样如果有两个人不想自杀,那么他们可以商量好各自排在第5位和第9位,因为他们是最后两个自杀的,也就是说到了最后就只剩下他们两个了,他们就可以不用自杀了,反正其他人都已经死了,没人知道他们俩作弊。

        参考代码:http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/JosephusProblem.htm

       
public class Josephus { public static void main(String[] args) {    Josephus j=new Josephus();     int[] man=j.jos(10, 2);     for(int e:man) System.out.print(e+"<<");     System.out.println();     for(int i=0;i<10;i++){     if(man[i]>=9){     System.out.println("作弊的人可以排在第 "+(i+1)+" 位");     }     }}public int[] jos(int number,int per){int man[]=new int[number];int pos=-1;for(int count=1;count<=number;count++){int i=0;while(i<per){pos=(pos+1)%number;if(man[pos]==0)i++;}man[pos]=count;}return man;}}


结果:

8<<1<<6<<2<<10<<3<<7<<4<<9<<5<<
作弊的人可以排在第 5 位
作弊的人可以排在第 9 位

把那两句改成约瑟夫的处境:

int[] man=j.jos(41, 3);

for(int i=0;i<41;i++){
       if(man[i]>=40){
        System.out.println("作弊的人可以排在第 "+(i+1)+" 位");
       }
      }

运行结果:

作弊的人可以排在第 16 位
作弊的人可以排在第 31 位