约瑟夫环 josephus

问题描述:   有 n 个人 围成一个环       从第start个人 开始    数 n_th个人     数到第n_th个人时   这个人出去 ,接着从这个人后再数n_th,一直循环,求最后一个出去得人 的序号

比如:   n=9,start=1,n_th=5

1 2 3 4 5 6 7 8 9    a[4]   第五个出去得:

1 2 3 4 6 7 8 9    

然后继续数 5个  去除a[0] 第一个

2 3 4 6 7 8 9

.....................

the sequence is: 5 1 7 4 3 6 9 2 8
the winner is: 8

这个过程是上述所说的一样,这个解决方案一共有两种解决方案

我们先看第一种   数组模拟

#include <iostream>
using namespace std;
#include <stdlib.h>
int main()
{
    int n,s,n_th;
    int a[1005];
    while (cin>>n>>s>>n_th)
    {
          int i,temp;
          for (i=0; i<n; ++i)
               a[i]=i+1;
          temp=s-1;
		  cout<<"the sequence is: ";
		  while (n>0)
		  {
			  temp=(temp+n_th-1)%n;
			  cout<<a[temp]<<" ";
			  for (i=temp+1; i<n; i++)
				  a[i-1]=a[i];
			  --n;
		  }
          cout<<endl<<"the winner is: "<<a[0]<<endl;
    }
    return 0;
}

 

第二种是数学解决方案:

具体推导过程如下:

假如我们知道这个子问题的解:例如ans是最终的胜利者,那么根据上面这个表把这个ans变回去

下面的是  以 第一个人为起点的即  start=1;

          ans=0;

  ∵ k=n_th%n;

  ∴ ans = ans+k = ans+ n_th%n ; 而 x+ n_th%n 可能大于n

  ∴ans= (ans+ n_th%n)%n = (ans+n_th)%n

  得到 ans=(ans+n_th)%n

     i  为 起点start

      a[1]=0;

      a[i]=(a[i]+n_th)%i;

现在换成是第start个人为起点时,也是一样的

 

#include <iostream>
using namespace std;
#include <stdlib.h>
int main()
{
    int n,s,n_th,res;
    int a[1005];
    while (cin>>n>>s>>n_th)
    {
          int i;
          for (i=0; i<n; ++i)
              a[i]=i+1;
          res=1;
          for (i=2; i<=n; i++)
          {
              res=(res+n_th)%i;
              if (0==res)
                  res=i;
          }
		  //此时   res为 s=1的情况
		  res=(res-1+s-1)%n+1;//变换
          cout<<"the winner is: "<<res<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值