Joseph Central Java to solve the problem

1 Joseph Central

Josephus problem originated in a Jewish story. Josephus problem along the following lines:

  The Romans captured the Qiaotapate, 41 individuals hidden in a cave escaped this catastrophe. The 41 individuals, including the historian Joseph (Joseph) and his friends. The remaining 39 people said they did not surrender to the Romans, decided to commit suicide. We decided on a suicide plan, all 41 individuals formed a circle, clockwise from the first individual number reported per number of people reported as 3 immediately commit suicide, and then the next person and then restart the count off, still each number is reported immediately to 3 people commit suicide ...... until everyone committed suicide so far.

  Joseph and some of his friends do not want to commit suicide, so Joseph think of a plan D, both of them equally involved in the scheme since the surgery, but eventually escaped the suicide. I ask, how they do it?

  One obvious way is to solve the individual 41 arranged in a ring, the inner ring is numbered clockwise as originally, the number of each of the outer ring 3 to the numerical order. You may be used in the array to hold the suicide Josephus data, and the array index as number of personnel involved in, and will be seen as an array of annular processed.
Here Insert Picture Description

package math_problem;

import java.util.Scanner;

public class JosephRingDemo {
    /**
     * @description : 约瑟夫环问题求解
     * @params : [number:总人数, key:关键字]
     * @return :
     * @time   : 2020/2/7 20:29
     */
    private static void josephRing(int number, int key) {
        // 若第 i 个人存活,则 men[i] == 0,否则 men[i] == 死亡序号
        int[] men = new int[number];
        int count = 0;          // 人的死亡序号
        int temp = 0, pos = -1; // pos:每个人对应的数组元素的下标
        while (number - count >= key) {
            do {
                pos = (pos + 1) % number;
                if (men[pos] == 0)
                    temp++;
                // 若对应的人该死,则跳出循环,显示数据
                if (temp == key) {
                    temp = 0;
                    break;
                }
            } while (true);

            // 将该自杀的人序号所对应的元素值由 0 变为 自杀序号
            men[pos] = ++count;
            System.out.printf("第 %-3d 个人自杀!初始位置编号为 %-3d ,\n", count, pos + 1);
        }

        System.out.print("\n可存活的人的初始位置编号为:");
        for (int j = 0; j < number; j++) {
            if (men[j] == 0) {
                System.out.printf("%-3d,", j + 1);
            }
        }
    }

    public static void main(String[] args) {
        josephRing(41, 3);
    }
}

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  ,

可存活的人的初始位置编号为:1631
Process finished with exit code 0

2 complex Josephus

Historically, Josephus been extensively studied. A generalized Josephus problem as follows:

  There are n individual ring sitting in a circle, clockwise sequentially numbered 1,2,3, ..., m. A black box placed in many paper, on which a random number is written. Each randomly selected a note, the note number is on the list of numbers. When the game starts, the columns optionally a number. Start from the first person, in numerical order beginning from a packet sequence number, the person report m columns, while their hands out of the column as the new digital numbers. Then, starting from the next person again from number 1 newspaper, reported that the number so the cycle continues. What people ask what is left?

  First to analyze this issue, compared with the previous Josephus, there is obviously complicated, mainly reflected in:

"The number of participants n is a variable, and therefore can not be used to represent an array, you should be used to represent the list structure. Further, these n individual end to end to form a ring, and therefore should be used to handle this circular list.

package math_problem;

import java.util.Scanner;

class LNode {
    int no;         // 游戏者编号
    int key;        // 保存游戏者出列数字
    LNode next;     // 指向下一个节点

    public LNode(int no, int key, LNode next) {
        this.no = no;
        this.key = key;
        this.next = next;
    }

    public LNode(int no, int key) {
        this.no = no;
        this.key = key;
    }
}

// 循环链表:尾指针 next 指向头结点
public class CircularLinkedList {
    static LNode head = null;
    static LNode tail = null;
    int listLen = 0;

    private void addHead(int no, int key) {
        // 新建头结点,此时 head.next 为空
        head = new LNode(no, key, null);
        // 只有一个结点,头结点也是尾结点
        if (tail == null)
            tail = head;
        listLen++;
    }

    private void addTail(int no, int key) {
        // 新建结点作为尾结点的后继结点
        tail.next = new LNode(no, key);
        // 将新建结点作为新的尾结点
        tail = tail.next;
        // 使新尾结点的 next 指向 head,使链表成环
        tail.next = head;
        listLen++;
    }

    /**
     * @description : 求解复杂的约瑟夫环
     * @params : [cListHead:第一个开始游戏的人, key:第一个出列数字]
     * @return : 
     * @time   : 2020/2/7 22:43
     */    
    private static void josephRing(LNode cListHead, int key) {
        // 先使 tempHead 指向序号为 1 的游戏者
        LNode tempHead = cListHead, tempTail = cListHead;
        // 使 tempTail 指向序号最大的游戏者
        while (tempTail.next != tempHead)
            tempTail = tempTail.next;

        System.out.println("游戏者出列顺序为:");
        // 若剩余人数 > 1,则一直循环
        while (tempHead.next != tempHead) {
            // 搜寻该出列的游戏者,并用 tempHead 指向该游戏者
            for (int i = 0; i < key - 1; i++) {
                // 将 tempTail 作为 tempHead 的前驱节点
                tempTail = tempHead;
                tempHead = tempHead.next;
            }
            tempTail.next = tempHead.next;

            System.out.println("出列序号:" + tempHead.no + " ,下一个出列数字:" + tempHead.key);
            key = tempHead.key;         // 更新出列数字
            tempHead = null;            // 从链表中删除出列的游戏者
            tempHead = tempTail.next;   // 从出列者下一位重新开始游戏
        }
        System.out.println("最后一个人的序号:" + tempHead.no + " ,出列数字:" + tempHead.key);
    }

    public static void main(String[] args) {
        System.out.println("约瑟夫环问题求解:");

        System.out.print("请输入游戏人数:");
        Scanner scanner = new Scanner(System.in);
        int number = scanner.nextInt();

        System.out.print("请按顺序输入每个人手中的出列数字:");
        // 初始化第一个游戏者的信息
        CircularLinkedList circularLinkedList = new CircularLinkedList();
        int key = scanner.nextInt();
        circularLinkedList.addHead(1, key);
        // 初始化剩余游戏者的信息
        for (int i = 2; i <= number; i++) {
            key = scanner.nextInt();
            circularLinkedList.addTail(i, key);
        }

        System.out.print("请输入第一次出列的数字:");
        key = scanner.nextInt();
        josephRing(head, key);
    }
}

约瑟夫环问题求解:
请输入游戏人数:8
请按顺序输入每个人手中的出列数字:3 5 6 2 1 5 7 2
请输入第一次出列的数字:4
游戏者出列顺序为:
出列序号:4 ,下一个出列数字:2
出列序号:6 ,下一个出列数字:5
出列序号:3 ,下一个出列数字:6
出列序号:5 ,下一个出列数字:1
出列序号:7 ,下一个出列数字:7
出列序号:8 ,下一个出列数字:2
出列序号:2 ,下一个出列数字:5
最后一个人的序号:1 ,出列数字:3

Process finished with exit code 0
Published 50 original articles · won praise 38 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_42250302/article/details/104215326