一:约瑟夫环(原版)
约瑟夫问题:n个人围成一圈,初始编号从1~n排列,从约定编号为x的人开始报数,
数到第m个人出圈,接着又从1开始报数,报到第m个数的人又退出圈,以此类推,
最后圈内只剩下一个人,这个人就是赢家,求出赢家原本的编号。
#include<algorithm>
#include<iostream>
using namespace std;
int main() {
int a[1001] = { 0 }; //初始化化数组作为环
int n, m;//n代表总的人数,m代表报数到几退出
cin >> n >> m;
int count = 0;//记录退出的个数
int k = -1;//这里假定开始为第一个人,下标为0,编号为1,如需从编号x开始,则k=x-2
while (count < n - 1) { //总共需要退出n-1个人
int i = 0;//记录当前报数编号
while (i < m) {
k = (k + 1) % n; //循环处理下标
if (a[k] == 0)
{
i++;
if (i == m)
{
a[k] = -1;
count++;
}
}
}
}
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
printf("%d\n", i + 1);
break;
}
}
}
二:约瑟夫环问题变形
编号为1…N的N个小朋友玩游戏,他们按编号顺时针围成一圈,
按顺时针次序报数,从第1个人报到第M个人出列;然后再从下个人开始报到第M+1个人出列;
再从下一个人开始报到第M+2个人出列……以此类推不断循环,直至最后一人出列。
请编写程序按顺序输出出列人的编号。
很久以前用链表写的
#include <iostream>
#include<string>
using namespace std;
typedef struct shuju
{
int s;
struct shuju *next;
}sj;
sj*pre,*head,*node;
int main()
{
int n, m,i,k=0,st=0;
cin >> n >> m;
head = new sj;
head->s = 1;
node = head;
for (i = 2; i <= n; i++)
{
pre = new sj;
pre->s = i;
node->next = pre;
node = pre;
}
node->next = head;
node = head; //创建循环链表
if(m==1)
for (i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
node = node->next;
}
if(st==0)
{
cout << "1" << " "; k++; st = 1;
}
if (k <n)
{cout << node->next->s << " "; k++;}
node->next = node->next->next;
node = node->next;
m++;
}
else
{
for (i = 1; i <= n; i++)
{
for (int j = 1; j < m - 1; j++)
{
node = node->next;
}
if (k <= n)
{
cout << node->next->s << " "; k++;
}
node->next = node->next->next;
node = node->next;
m++;
}
}
}