本人比较笨,约瑟夫问题的求解方法想了好久才想通,在这里留一篇文章,记录一下。
约瑟夫问题:n个人,数m,列出顺序。
1,用算法模拟数数过程,通过一个一个的排除,最后得到最终的结果:
首先解决思路问题,每次数数m个,一共数n次,所以一共经过n*m次,然后定义一个int t,用来算作每个人报数的时候报出的数,
然后没报一下,判断所在的是否还存在,只有两个问题,一个是是否到了末尾,如果到了末尾就转到前面去;然后判断是否已经数出,如果数出,直到
没有数出的数为止做while循环。每次做完一个m,就要归零(输出一个被数出的人),因为是从零开始的,所以输出的人要加上1.
for(int i=0;i<n;i++){ for(int i0=0;i0<m;i0++){//此为一共计算的n*m次 t++;//报数 if(t==n) t=0; while(monkey[t]==0){ t++; if(t==n) t=0; } } // cout<<t+1<<endl; monkey[t]=0; if(i==n-1) cout<<t+1<<endl;; }
上述的算法s
2.用递推的方法求解:
因为直接要求的最后的一个人用以下形式来表示:
0 1 2 3 4 5 。。。。。 n-1,
在排除第一个人的时候,当n》m时,排除的是第m个,(代号为m-1),当n》m时,第n-m个,排除的是(n-m-1),所以排除的是第m mod n个
再将所有的重新排列一下为
m m+1 m+2 m+3 。。。。n-1 0 1 2 3 。。 m-2,,将其看作从
0 1 2 3 4 。。。。。 n-2,根据前面的算式,转换成n-1个人的约瑟夫问题,如果知道是第x个人是n-1个人约瑟夫问题的最后的人,根据以上的表,就能够知道第n人的约瑟夫问题最后一个人是谁
所以关键就是求出递推关系,怎么从n-1人的约瑟夫问题的解转换到n人约瑟夫问题的解:
n-1个人约瑟夫问题(x)的第二重排除根据n人约瑟夫问题(x‘)来推导,x'=(x+m) mod n
(如果第0是最后胜利者,则m mod n=m为最后胜利者)
以后就是根据递推关系,根据1人约瑟夫问题的解为它本身,求出n人约瑟夫问题的解
#include <iostream> using namespace std; int main() { int n,m; while(1){ cin>>n>>m; if(n==0&&m==0) return 0; int k=0; for(int i=1;i<=n;i++){ k=(k+m)%i; } cout<<k+1<<endl;//计算从0开始,实际从1开始 } }