约瑟夫环 josephus

来源:互联网 发布:ksc歌词制作软件下载 编辑:程序博客网 时间:2024/05/20 05:28

问题描述:   有 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;}