約瑟夫環:遞歸算法(唐伯虎點秋香)


約瑟夫環:遞歸算法

 

 

 

 

假設下標從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 ());
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM