什么是约瑟夫问题?
约瑟夫问题是一个有名的问题,编号为1-N的N个人安顺时针围坐一圈,选取M为报数的上限,从第一个人按顺时针开始报数,将第M个人出列,,下一个人继续从1开始报数,报到M的人再出列,直至所有的人全部出列为止。
数组方法实现
#include <iostream>
using namespace std;
//n是有几个人,m为有删除间隔,s为开始下标
int Joseph(int n, int m, int s)
{
if (n < m || n <= 0 || m <= 0) {
throw logic_error("输入的值错误");
}
int num = 1;//num为当前的值
int cnt = 0;//cnt为删除的个数
int* arr = new int[n];
//初始化动态数组
for (int i = 0; i < n; i++)
arr[i] = i;
while (cnt < n) {
while (num < m)
{ //往后走一位
s = (s + 1) % n;
//判断下一位是否是已经被删除掉的(删除值我用将-1赋值给该元素表示)
if (arr[s] != -1) {
num++;
}
}
cnt++;
arr[s] = -1;
//找一找下面第几个人报数为1
if (cnt < n) {
num = 1;
while (arr[s] == -1) {
s = (s + 1) % n;
}
}
}
delete []arr;
arr = NULL;
return s;
}
int main()
{
int n, m, s;
cin >> n >> m >>s;
cout<<"the winner is "<<Joseph(n,m,s);
return 0;
}
链表方式实现
#include <iostream>
using namespace std;
typedef struct Node
{
int data;
struct Node* next;
};
int Josephu(int n, int m)
{
int i, j;
Node* head, * tail;
//分配空间
head = tail = new Node;
//创建循环链表
for (i = 1; i < n; i++)
{
tail->data = i;
tail->next = new Node;
tail = tail->next;
}
tail->data = i;
tail->next = head;
for (i = 1; tail != head; i++)
{
for (j = 1; j < m; j++)
{
tail = head;
head = head->next;
}
tail->next = head->next;
cout << i << "名出局" << head->data << endl;
delete head;
head = NULL;
head = tail->next;
}
i = head->data;
delete head;
head = NULL;
return i;
}
int main()
{
int n, m;
cin >> n >> m;
cout << "the winner is " << Josephu(n, m);
}