约瑟夫环:递归算法(唐伯虎点秋香)
约瑟夫环:递归算法
假设下标从0开始,0,1,2 .. m-1共m个人,从1开始报数,报到k则此人从环出退出,问最后剩下的一个人的编号是多少?
现在假设m=10
0 1 2 3 4 5 6 7 8 9 k=3
第一个人出列后的序列为:
0 1 3 4 5 6 7 8 9
即:
3 4 5 6 7 8 9 0 1(*)
我们把该式转化为:
0 1 2 3 4 5 6 7 8 (**)
则你会发现: ((**)+3)%10则转化为(*)式了
也就是说,我们求出9个人中第9次出环的编号,最后进行上面的转换就能得到10个人第10次出环的编号了
设f(m,k,i)为m个人的环,报数为k,第i个人出环的编号,则f(10,3,10)是我们要的结果
当i=1时, f(m,k,i) = (m+k-1)%m
当i!=1时, f(m,k,i)= ( f(m-1,k,i-1)+k )%m
所以程序如下:
int fun(int m,int k,int i){ if(i==1) return (m+k-1)%m; else return (fun(m-1,k,i-1)+k)%m; } int main(int argc, char* argv[]) { for(int i=1;i<=10;i++) printf("第%2d次出环:%2d\n",i,fun(10,3,i)); return 0; }
第 1次出环: 2 第 2次出环: 5 第 3次出环: 8 第 4次出环: 1 第 5次出环: 6 第 6次出环: 0 第 7次出环: 7 第 8次出环: 4 第 9次出环: 9 第10次出环: 3
数学解(提供思路):
参考C#做法(据说不是很好)
常用算法(C#): 约瑟夫环问题 约瑟夫环问题: 设有n个人围坐在圆桌周围,现从某个位置m(1≤m≤n)上的人开始报数,报数到k的人就站出来。 继续下一个人,即原来的第k+1个位置上的人,又从1开始报数,再报数到k的人站出来。依此重复下去,直到全部的人都站出来为止 using System; using System.Collections.Generic; using System.Text; namespace ExJose { class ClassJose { //从第start人开始计数,以alter为单位循环记数出列,总人数为total public int[] Jose(int total, int start,int alter) { int j, k = 0; //count数组存储按出列顺序的数据,以当结果返回 int[] count = new int[total + 1]; //s数组存储初始数据 int[] s = new int[total + 1]; //对数组s赋初值,第一个人序号为0,第二人为1,依此下去 for (int i = 0; i < total; i++) { s[i] = i; } //按出列次序依次存于数组count中 for (int i = total; i >= 2; i--) { start = (start + alter - 1) % i; if (start == 0) start = i; count[k] = s[start]; k++; for (j = start + 1; j <= i; j++) s[j - 1] = s[j]; } count[k] = s[1]; //结果返回 return count; } static void Main(string[] args) { ClassJose e=new ClassJose (); int[] a = e.Jose(10,3,4); for (int i = 0; i < a.Length; i++) { Console.WriteLine(a[i].ToString ()); } } } }