约瑟夫环问题

约瑟夫环问题:
41个犹太人为了表示不像罗马人屈服,决定集体自杀,其中由约瑟夫和他的朋友,他们两个不想自杀。自杀的规则是41个人围成圈,轮流报数,报到3的自杀,下一个从1开始从新报,以此类推。
约瑟夫和他的朋友想活下来就要让他们成为最后两个人,然后放弃自杀规则。问约瑟夫和他的朋友应该在环的哪两个位置?

public static int[] Josep(int total,int live){
        int[] dieOrder=new int[total];//记录约瑟夫编号,即死亡顺序
        for(int i=0;i<total;i++){//逐个初始化
            dieOrder[i]=0;
        }

        int i=0;//游标
        int call=1;//报数
        int die=0;//死亡人数

        while(die<total-live){
            if(i==total){
                i=0;//如果到尾回到头,形成环
            }
            if(dieOrder[i]==0){//活人计数
                if(call<3){
                    call++;
                }else{
                    dieOrder[i]=++die;//记录约瑟夫编号
                    //System.out.println("第"+die+"个自杀的人是 "+(i+1)+"号");
                    call=1;
                }  
            }
            i++;//移动位置
        }

        int[] survive=new int[live];
        int k=0;
        System.out.print("可以活下来的位置是:");
        for(int j=0;j<total;j++){
            if(dieOrder[j]==0){
                System.out.print(j+1+" ");
                survive[k]=j+1;
                k++;
            }
        }
        return survive;

    } 
    public static void main(String[] args){
        JosepCircle.Josep(41, 2);


    }
第1个自杀的人是 3号
第2个自杀的人是 6号
第3个自杀的人是 9号
第4个自杀的人是 12号
第5个自杀的人是 15号
第6个自杀的人是 18号
第7个自杀的人是 21号
第8个自杀的人是 24号
第9个自杀的人是 27号
第10个自杀的人是 30号
第11个自杀的人是 33号
第12个自杀的人是 36号
第13个自杀的人是 39号
第14个自杀的人是 1号
第15个自杀的人是 5号
第16个自杀的人是 10号
第17个自杀的人是 14号
第18个自杀的人是 19号
第19个自杀的人是 23号
第20个自杀的人是 28号
第21个自杀的人是 32号
第22个自杀的人是 37号
第23个自杀的人是 41号
第24个自杀的人是 7号
第25个自杀的人是 13号
第26个自杀的人是 20号
第27个自杀的人是 26号
第28个自杀的人是 34号
第29个自杀的人是 40号
第30个自杀的人是 8号
第31个自杀的人是 17号
第32个自杀的人是 29号
第33个自杀的人是 38号
第34个自杀的人是 11号
第35个自杀的人是 25号
第36个自杀的人是 2号
第37个自杀的人是 22号
第38个自杀的人是 4号
第39个自杀的人是 35号
可以活下来的位置是:16 31 

更复杂的约瑟夫环是自杀规则不定,每个人有一个数字,一个人自杀后,后面的人需要报数到这个数字才自杀。需要更灵活:

public static int[] hardJosep(int total,int live,int[] no){//no存储每个人的自杀规则数字
        int[] dieOrder=new int[total];//记录约瑟夫编号,即死亡顺序
        for(int i=0;i<total;i++){//逐个初始化
            dieOrder[i]=0;
        }

        int i=0;//游标
        int call=1;//报数
        int die=0;//死亡人数
        int callNum=no[0];
        while(die<total-live){
            if(i==total){
                i=0;//如果到尾回到头,形成环
            }
            if(dieOrder[i]==0){//活人计数
                if(call<callNum){
                    call++;
                }else{
                    dieOrder[i]=++die;//记录约瑟夫编号
                    System.out.println("第"+die+"个自杀的人是 "+(i+1)+"号");
                    call=1;
                    callNum=no[i];
                }  
            }
            i++;//移动位置
        }

        int[] survive=new int[live];
        int k=0;
        System.out.print("可以活下来的位置是:");
        for(int j=0;j<total;j++){
            if(dieOrder[j]==0){
                System.out.print(j+1+" ");
                survive[k]=j+1;
                k++;
            }
        }
        return survive;

    } 

当no都是3时和普通约瑟夫环相同,当给no附复杂的数组,就会产生不同的结果。

    public static void main(String[] args){
        //JosepCircle.Josep(41, 2);
        int[] no=new int[41];
        for(int i=0;i<41;i++){
            no[i]=i+1;
        }
        JosepCircle.hardJosep(41, 2, no);

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值