约瑟夫求生最初版本:
在罗马人占领乔塔帕特后,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了,交给系统吧