约瑟夫问题
约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
例如只有三个人,把他们叫做A、B、C,他们围成一圈,从A开始报数,假设报2的人被杀掉。
- 首先A开始报数,他报1。侥幸逃过一劫。
- 然后轮到B报数,他报2。非常惨,他被杀了
- C接着从1开始报数
- 接着轮到A报数,他报2。也被杀死了。
- 最终胜利者是C
核心在于关注胜利者的下标位置是怎么变的。每杀掉一个人,其实就是把这个数组向前移动了M位。
每杀掉一个人,其实就是把这个数组向前移动了M位。然后逆过来,就可以得到这个递推式。
#include<bits/stdc++.h>
using namespace std;
int josephus(int n,int m)
{
if(n==1)
return 0;
else
return (josephus(n-1,m)+m)%n;
}
int main()
{
int n,m;
cin>>n>>m;
cout<<josephus(n,m);
return 0 ;
}
简化之后代码变成循环的过程。
求出的结果是数组中的下标,最终的编号还要加1
把n个人依次排列好,p是数组下标
#include <iostream>
using namespace std;
int josephus(int n,int m)
{
int p=0;//p为数组下标
for(int i=2;i<=n;i++)//n=1时只有一个人,直接胜利,否则进行n-1次循环
{
p=(p+m)%i;
}
return p+1;//求出的结果是数组中的下标,最终的编号还要加1
}
int main() {
int n,m;
cin>>n>>m;
cout<<josephus(n,m);
return 0;
}