zoukankan      html  css  js  c++  java
  • 约瑟夫问题

    约瑟夫问题

    问题描述

    据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

    然而Josephus 和他的朋友并不想玩这游戏,于是Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。他是怎么计算16和31这两个位置的?

    解法

           问题比较简单,也比较有意思.可用代数来解决此问题.

           假设,

    人的序号:1,2,3,4,5,6,7,8,9,10,……,38,39,40,41

    对应数组:0,0,0,0,0,0,0,0,0, 0, ……,0,0,0,0

           每轮数数的时候,只数0,如0,1,2,0,0,那么这一轮,最后一个0才是一轮的结束.因为前面两个已经自杀了,再数他就违反游戏规则了.

           按照这个规则,我们可用设计一个循环,来进行数数和标记

    for(int count = 1, pos = -1; count <= number; count++) { //1
                int i = 0;                        //2            
                while(i != per) {                                //3
                    pos = (pos+1) % number;                       //4
                    if(man[pos] == 0)                             //5
                        i++;                               //6
                }
                man[pos] = count;                         //7
    } 
    

    序号1代表循环41次,因为41个人嘛

    序号2代表,数数的当前值

    序号3代表,当数数的值等于每轮技术值(per)就结束循环,也就是说,当数数值=3,那么一轮结束.

    序号4,当前位置pos是依次递增的,所以当他到41时候,下一个应该是0

    序号5,当遇到的人没死,也就是值=0,才能,数数值才能+1

    序号7,当一轮结束后,标记最后数数的那个人(pos位置)为第count个自杀的人

    完整代码

    public class Josephus {
    public static int[] josephus(int number, int per) {
            int[] man = new int[number]; 
            for(int count = 1, pos = -1; count <= number; count++) { 
                int i = 0;
                while(i != per) { 
                    pos = (pos+1) % number; 
                    if(man[pos] == 0) 
                        i++;
                } 
                man[pos] = count; 
            } 
            return man;
        }
     
        public static void main(String[] args) {
            int[] man = josephus(41, 3);
     
            System.out.println("约琴夫排列:"); 
            for(int m : man) System.out.print(m + " "); 
     
            System.out.println("\nL表示3个存活的人要放的位置:"); 
            for(int i = 0; i < 41; i++) { 
                System.out.printf(man[i] <= 41 - 3 ? "D" : "L");
                System.out.printf((i+1) % 5 == 0 ? " " : "");
            } 
        }
    }
    

    整理编辑: 东苑草根 zjut
  • 相关阅读:
    遥控器拆卸记录
    计算器拆卸记录
    no matching constructor for initialization
    STL
    排序方法
    二叉树之广度优先遍历
    C++之queue学习记录
    方向电路
    站间联系电路
    求二叉树的最大深度
  • 原文地址:https://www.cnblogs.com/dycg/p/1791767.html
Copyright © 2011-2022 走看看