Josephus 问题。有 n 个人围成一圈,排序排号,从第一个人开始报数(从 1 到 3 报数), 凡报到 3 的人退出圈子,按顺序依次输出退出的人的编号。
时间: 2023-12-23 16:50:22 浏览: 68
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉 例如N=6,M=5
5星 · 资源好评率100%
可以使用循环链表来模拟这个过程。首先将 n 个人连成一个环,然后从第一个人开始报数,每报到 3 就将该人从环中删除。重复这个过程直到只剩下一个人为止,期间删除的人的编号即为 Josephus 问题的解。
具体实现过程如下:
1. 定义一个结构体表示每个人,结构体中包括编号和指向下一个人的指针。
```c++
struct Person {
int id;
Person *next;
};
```
2. 创建 n 个人,连成一个环。
```c++
Person *createCircle(int n) {
Person *head = new Person{1, nullptr};
Person *curr = head;
for (int i = 2; i <= n; i++) {
curr->next = new Person{i, nullptr};
curr = curr->next;
}
curr->next = head;
return head;
}
```
3. 按照规则报数并删除人。
```c++
void josephus(int n) {
Person *head = createCircle(n);
Person *prev = nullptr, *curr = head;
int count = 0;
while (head->next != head) { // 只剩下一个人时结束循环
count++;
if (count == 3) {
count = 0;
cout << curr->id << " "; // 输出删除的人的编号
prev->next = curr->next; // 删除当前节点
Person *temp = curr;
curr = curr->next;
delete temp;
} else {
prev = curr;
curr = curr->next;
}
}
cout << head->id; // 输出最后剩下的人的编号
delete head;
}
```
完整代码如下:
阅读全文