约瑟夫问题 循环链表简单解决

约瑟夫求生最初版本:
在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏

就借助最初版本复习一下循环链表吧

人与人之间手拉手形成环,每个人就是一个链表结点,结点的删除就是这个人狗带

#include <iostream>
#include <stdio.h>
#include <algorithm>

using namespace std;

struct person {
    
    
    int id;
    person *next;
};

void kill(person *p) {
    
     //杀掉这个人
    person *thenext = p->next;
    p->id = thenext->id;
    p->next = thenext->next;
    delete thenext;
}

int main() {
    
    
    int sum;//总人数
    cout << "一共几个人:";
    cin >> sum;
    cout << "几号狗带:";
    int flag;//报该数的狗带
    cin >> flag;
    person *head = new person;
    person *temp = head;
    for(int i = 1; i <= sum; i++) {
    
    //形成循环链表,1~sum编号
        if(i == sum) {
    
    //最后一个人
            temp->id = i;
            temp->next = head;
        } else {
    
    
            temp->id = i;
            person *other = new person;
            temp->next = other;
            temp = other;
        }
    }
    person *t = head; //遍历链表的结点
    cout << "狗带顺序为:";
    for(int i = 1; sum >= flag; i++) {
    
    //循环条件为剩余人数大于待杀编号
        if(i == flag) {
    
    //此人被杀
            cout << t->id << " ";
            kill(t);
            sum--;
            i = 0;
        } else {
    
    
            t = t->next;
        }
    }
    cout << endl;
    if(sum > 0) {
    
    
        cout << "活下来的是:";
        person *first = t;
        do {
    
    //最后活着的人的编号
            cout << t->id << " ";
            t = t->next;
        } while(t != first);
    } else {
    
    
        cout << "所有人都狗带了" << endl;
    }
    return 0;
}

懒得结点一个个delete了,交给系统吧在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ccmtvv/article/details/105981799