🏆今日学习目标:
🍀例题讲解1748:约瑟夫问题
✅创作者:贤鱼
⏰预计时间:15分钟
🎉个人主页:贤鱼的个人主页
🔥专栏系列:c++
🍁贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团
1748:约瑟夫问题
- 题目
- 思路
- AC代码
题目
总时间限制: 1000ms 内存限制: 65536kB
-
描述
约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。 -
输入
每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是:
0 0
- 输出
对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号
样例输入
6 2
12 4
8 3
0 0
样例输出
5
1
7
思路
我们要首先理解题意
- 首先简化题目
- 1所有猴子的顺序可以理解为一个
环
- 2考虑每次报数下一只猴子是哪位
- 3找到目标猴子,删掉他
就这几个问题
环很好解决,我们用结构体a来模拟链表
a[].l就是a左边的数字,r就是右边的数字
当i等于1的时候,a.l等于n就好,和最后一个相连,同理i等于n时r等于1
所以报数内容也很好解决,假设现在是j猴子,下次报数直接a[j].r开始不就好啦?
其他内容代码里都有,一看就会,如果有任何问题欢迎私信
AC代码
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int l,r;
}a[100005];
int n,m;
void dl(int x){//这个内容不理解的话找个数据画一画就会啦
if(a[x].l==-1) return;
a[a[x].l].r=a[x].r;
a[a[x].r].l=a[x].l;
a[x].l=-1;
a[x].r=-1;
}
int main(){
while(1){
cin>>n>>m;
if(n==1){
cout<<1<<endl;
continue;
}
for(int i=1;i<=n;i++){//搞个环出来
if(i==1){
a[i].l=n;
a[i].r=2;
}else if(i==n){
a[i].r=1;
a[i].l=i-1;
}else{
a[i].r=i+1;
a[i].l=i-1;
}
}
if(n==0&&m==0){
return 0;
}
int j=1;
while(1){
for(int i=1;i<m;i++){//找猴子
j=a[j].r;
}
if(n==1){
cout<<j<<endl;
break;
}
int k=j;
j=a[j].r;//直接让j去下一个猴子的位置,方便从上面找猴子继续报数
dl(k);
n--;
}
}
}