c++解决约瑟夫环问题
问题背景
约瑟夫(Josephus)问题:
-
m个人围坐成一圈,从1开始顺序编号
-
游戏开始,从第一个人开始由1到n循环报数
-
报到m的人退出圈外
问:
最后留下的那个人原来的序号
问题分析
本题可以定义一个容器(vector),初始化大小(元素个数)为n。容器里元素的值标识该人是否出局,1在圈内,0出局。值为0的人不再参与报数,可以用一个整数型k做计数器,采用倒计数,记录留下的人数。
代码解决
引用库
#include<iostream>
#include<vector>
using namespace std;
利用一个main函数解决问题,并完成初始化
int main()
{
int m,n,k,p,number=0,i;
cout << "请输入总人数m以及循环号码n:";
cin >> m >> n;
k = m;
vector<bool> left(m, 1);
m表示总人数,n表示报数的号码,k对应场内剩余的人数,number代表每一轮开始报数的位置,i作为中间量在后续代码中被使用。
while (k > 1)
{
i = number; //i记录循环开始位置
number = n % k - 1; //number 记录要往后移动几个人
if (number < 0) number += n;
for (int j = 1; j <= number; i++)
{
if (left[(i + j) % m] != 0) j++;
}
left[i % m] = 0; //找到最后一个并置零
p = i + 1; //寻找下一个循环开始位置
while (1)
{
if (left[p % m] != 0) break;
else p++;
}
number = p%m;
k--;
}
注意:报数过程和开始下次报数时都要进行判断,当前所在位置其值是否为0,若为0则要跳过。
以下是最终的完整代码
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int m,n,k,p,number=0,i;
cout << "请输入总人数m以及循环号码n:";
cin >> m >> n;
k = m;
vector<bool> left(m, 1);
while (k > 1)
{
i = number; //i记录循环开始位置
number = n % k - 1; //number 记录要往后移动几个人
if (number < 0) number += n;
for (int j = 1; j <= number; i++)
{
if (left[(i + j) % m] != 0) j++;
}
left[i % m] = 0; //找到最后一个并置零
p = i + 1; //寻找下一个循环开始位置
while (1)
{
if (left[p % m] != 0) break;
else p++;
}
number = p%m;
k--;
}
cout << "最后剩下的人为:" << number + 1 << "号";
return 0;
}
欢迎指正