2037:【例5.4】约瑟夫问题
题目描述
N N N个人围成一圈,从第一个人开始报数,数到 M M M的人出圈;再由下一个人开始报数,数到 M M M的人出圈;…输出依次出圈的人的编号。
输入格式
输入 N N N和 M M M。
输出格式
输出一行,依次出圈的人的编号。
输入样例
8 5
输出样例
5 2 8 7 1 4 6 3
提示
数据范围
对于所有数据, 2 ≤ N , M ≤ 1000 2 \le N,M \le 1000 2≤N,M≤1000。
思路
这一题约瑟夫问题可以用多种方法求解,如容器,栈
AC代码如下
数组模拟
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,m,j,a[1010],sum=0,i=0;//j计数变量,数m个数
cin>>n>>m;
memset(a,1,sizeof(a));//a[1010]全为1
while(i!=n) { //重复执行n次
j=0;
while(j<m) {//讲未出圈的人进行循环
sum++;
if(sum>n)sum=1;//要是超出n,sum继续从1数起
if(a[sum]!=0)j++;//计算人数
}
a[sum]=0;//讲sum设为已出圈,输出sum
cout<<sum<<" ";
i++;
}
}
队列
#include<bits/stdc++.h>
using namespace std;
int main() {
queue<int> q;//定义队列q
int n,m,i=1;
cin>>n>>m;
for(i=1; i<=n; i++) {
q.push(i);
}//给圈里的每一个人编号
i=1;
while(!q.empty()) {//如果所有人没有全部出圈
int l=i;
for(; i<l+m-1; i++) {//进行数数,数m-1次
q.push(q.front());//将队首放入队尾来模拟报数
q.pop();//删除队首
}
cout<<q.front()<<' ';//输出报到m的人
q.pop();//删除报到m的人
}
return 0;
}
容器
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,m,i=1;
cin>>n>>m;
vector<int> q;//定义容器q
q.clear();//将q清空
for(i=1; i<=n; i++) {
q.push_back(i);
}//给圈里的每一个人编号
i=1;
while(!q.empty()) {//如果所有人没有全部出圈
int l=i;
for(; i<l+m-1; i++) {//进行数数,数m-1次
q.push_back(q.front());//将容器之首放入容器之尾来模拟报数
q.erase(q.begin(),q.begin()+1);//删除容器之首
}
cout<<q.front()<<' ';//输出报到m的人
q.erase(q.begin(),q.begin()+1);//删除报到m的人
}
return 0;
}
链表
#include<bits/stdc++.h>
using namespace std;
int a[1005];
int main() {
int n,m;
cin>>n>>m;//输入n、m
for(int i=0; i<n; i++) //初始化
a[i]=i+1;
a[n]=1;
int p=0;
for(int i=1; i<=n; i++) { //开始模拟出圈过程
for(int j=1; j<m; j++)
p=a[p];//p位置右移
cout<<p[a]<<" ";//输出出圈人的位置
a[p]=a[a[p]];//删掉出圈人
}
return 0;
}
再见,记得三连哦!