题目背景
约瑟夫是一个无聊的人!!!
题目描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
输入输出格式
输入格式:n m
输出格式:出圈的编号
输入输出样例
说明
m, n \le 100m,n≤100
思路:此题可利用模拟完成 模拟的方法有多种
1.利用队列模拟 如果没报到出列的数字之前 队首元素移至队尾 报的数字+1 如果报到要出列的数字 则队首出队 并输出该元素 知道队列的元素只剩一个为止;
AC代码:
#include <bits/stdc++.h>
#include <queue>
using namespace std;
int main()
{
queue<int> S;
int n, m, now_num = 1, out_num;
cin >> n >> m;
out_num = m;
if(n == 0 || m == 0)
{
return 0;
}
for(int i = 1; i<=n; i++)
S.push(i);//全部人都先入队
while(S.size()>1)
{
if(out_num == now_num)//该人是需要淘汰的ren
{
cout<<S.front()<<' ';
S.pop();//出队
now_num = 1;
}
else
{
S.push(S.front());//将队头移到队尾
S.pop();
now_num++;
}
}
cout<<S.front();
return 0;
}
2.用动态数组模拟位置 上一次的位置+m(即报数的大小)-1 然后确定其在数组的下标 将其输出 并删除,直到数组中只剩一个元素为止;
AC代码:
#include <bits/stdc++.h>
#include <vector>
using namespace std;
int main()
{
vector<int> S;
int n, m;
cin >> n >> m;
if(n == 0 || m == 0)
return 0;
for(int i = 1; i<=n; i++)
S.push_back(i);
int k = 0;
while(S.size()>1)
{
k = (k + m - 1) % S.size();//上一项的位置 移动m个步长后 由于0起步和1起步的差别 所以-1
cout<<S[k]<<' ';
S.erase(S.begin()+k);
}
cout<<S[0];
return 0;
}