【c/c++】约瑟夫环

约瑟夫问题

约瑟夫问题是个著名的问题: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白驹_过隙

听说打赏的都进了福布斯排行榜

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值