zoukankan      html  css  js  c++  java
  • 约瑟夫环详解

    约瑟夫环问题:一圈共有N个人,开始报数,报到M的人自杀,然后重新开始报数,问最后自杀的人是谁?

    如图:内环表示人排列的环,外环表示自杀顺序;上面N=41,M=3

    一.很容易想的是:建立一个动态数组,把1-n的编号放里面,每死一个人移除一个人,在记录下当前位置,递归到数组长度为1,就是活着的那个人了。

    下面的是代码:

    import java.util.ArrayList;
    import java.util.Scanner;
    public class 约瑟夫环 {
        public static ArrayList<Integer>arrayList;
        static{
            arrayList = new ArrayList<Integer>();
        }
        static void init(int n){
            arrayList.clear();
            for(int i = 1; i <= n; i++){
                arrayList.add(i);
            }
        }
        static int work(int ele, int pos){
            if(arrayList.size() == 1)
                return arrayList.get(0);
            else{
                int cur = (pos + ele - 1)%arrayList.size();
                if(cur == 0)
                    cur = arrayList.size();
                
                System.out.printf("%d死了
    ", arrayList.get(cur - 1));
                arrayList.remove(cur - 1);
                //System.out.println(arrayList.size());
                return work(ele, cur%arrayList.size() == 0?
                                arrayList.size() : cur%arrayList.size());
            }
        }
        
        public static void main(String[] args) {
            Scanner cin = new Scanner(System.in);
            int m, n;
            while(cin.hasNext()){
                n = cin.nextInt();
                m = cin.nextInt();
                init(n);
                System.out.printf("最后%d活着
    ", work(m, 1));
            }
        }
    }

    二.其实还有一种递推的解法。

    为了方便,我们在这里把这n个人的编号从0开始。那么我们去掉的人总是m%n-1,剩下n-1个人,这n-1个人又是一个从第m%n开始的新的约瑟夫环问题。

    这个写法初一看不好理解,那么我们把编号转变下:

    k     --> 0

    k+1   --> 1

    k+2   --> 2

    ...

    ...

    k-2   --> n-2

    k-1   --> n-1

    变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根

    据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变回去的公式很简单,相信大家都可以推出来:x=(x+k)%n

    如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就行了。(n-2)个人的解呢?当然是先求(n-3)的

    情况 ---- 这显然就是一个倒推问题!

    递推公式为:

    F(1,m) = 0;

    F(n,m) = (m%n + F(n-1, m))%n; n>= 2

    很容易得到代码:

    cin>>N;  
        cin>>M;  
        int result=0;//N=1情况  
        for (int i=2; i<=N; i++)  
        {  
            result=(result+M)%i;  
        }  
        cout<<"最后自杀的人是:"<<result+1<<endl;
  • 相关阅读:
    linux下源码安装python3
    FTP 命令
    Linux Shell数值比较和字符串比较及相关
    mount umount sort du tar
    linux 自动检查ssh脚本
    删除linux访问记录(message删不了)
    h3c 备份脚本
    linux 批量scp 脚本
    Linux 删除几天前的文件脚本
    博达交换机镜像检查,镜像丢失自动添加脚本
  • 原文地址:https://www.cnblogs.com/handsomecui/p/6053166.html
Copyright © 2011-2022 走看看