約瑟夫環問題

2021-06-29 04:04:01 字數 2450 閱讀 9632

問題描述:有n個人坐成一圈,編號為1到n,從編號為1的人開始傳遞熱馬鈴薯。m次傳遞之後,持有熱馬鈴薯的人退出遊戲,圈縮小,然後遊戲從退出人下面的人開始,繼續進行。最終留下來的人獲勝。這樣,如果m=0,n=5,那麼參加遊戲的人依次推出,5號獲勝。如果m=1,n=5,那麼退出的順序是2、4、1、5。

方法1:使用迴圈鍊錶的資料結構來解決。

**如下:

circularlist.h

//---------【利用迴圈鍊錶解決約瑟夫環問題】------------

#ifndef __circularlist__

#define __circularlist__

#include // 迴圈鍊錶的實現

class circularlist

};public:

circularlist(int n)

curr->next = first;

} ~circularlist()

delete first;

first = null;

} void printlist() const

std::cout << std::endl;

} // 時間複雜度:o(mn)

void erase(int m)

listnode *curr = first;

while(curr->next != curr)

std::cout << "the person out: " << curr->val << "\n";

prev->next = curr->next;

delete curr;

curr = prev->next;

first = curr;

printlist();

} first = curr;

std::cout << "the winner is " << curr->val;

}private:

listnode *first;

};#endif

main.cpp

//-----------------【約瑟夫環問題】--------------------

#include "circlelist.h"

using namespace std;

int main(int argc, char const *argv)

方法2:使用數學推導。

原問題可以解釋為編號為1到n的人,從編號為1的人開始喊數字0,下乙個喊數字1,依次類推,直到有人喊數字m,則這個人退出遊戲。下乙個人又從0開始喊,直到只剩乙個人。

原序列1:1,.......,k-2,k-1,k,......,n(其中序號k-1出列)。

由推導可得,出列的序號為(m+1)%n(因為m可能比n大),所以有k-1=(m+1)%n,即k=(m+2)%n。

出列後得到序列2:1,.......,k-2,k,......,n。

將前面的k-2個元素放到序號n的後面,則得到序列3:k,......,n,1,.......,k-2。

將序號1及後面的序號全部加上n,則得到序列4:k,......,n,n+1,......,n+k-2。

再將全部序號減去k-1,得到序列5:1,......,n-1。

由於最後的勝利者在序列1中,也肯定在序列5中,設其在序列5中的序號為x,在序列1中的序號為x』,現在問題變為推導x和x'的關係。

從序列5到序列4,全部加上k-1即可,即x'=x+k-1。

其中比較難的的推導是從序列4到序列3,也就是將序列n+1,......,n+k-2這一部分變為1,......,k-2,其實就是對n取餘數,即x'=(x+k-1)%n。由於k=(m+2)%n,故x'=(x+m+1)%n。需要注意的是此時n會變為0,需要將其修改回來。

從序列3到序列2和序列1,序號沒有改變。

所以我們可以總結如下:

設i為剩餘參加比賽的人數,f[i]為最終勝利者的序號,有

f[1]=1;f[i]=(f[i-1]+m+1)%i(i>1);如果f[i]==0,f[i]=i。

**如下:

#include int main(int argc, char const *argv)

printf("%d\n", winner);

return 0;

}

這種型別的問題還有其它的類似遞推公式:

f[1]=0;f[i]=(f[i-1]+m)%i(i>1):人的序號為0到n-1,數字從1開始喊到m的情況。

f[1]=1;f[i]=(f[i-1]+m)%i(i>1);如果f[i]==0,f[i]=i:人的序號為1到n,數字從1開始喊到m的情況。

將上面第一種情況的結果加上1也可得到第二種情況的結果,或者寫成f[1]=1;f[i]=(f[i-1]+m-1)%i 

+ 1(i>1)。

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...

約瑟夫問題 約瑟夫環

約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...

約瑟夫環問題

約瑟夫環問題 問題描述 編號是1,2,n的n個人按照順時針方向圍坐一圈,每個人持有乙個密碼 正整數 一開始任選乙個正整數作為報數上限值m,從第乙個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向的下乙個人開始重新從1報數,如此下去,直到所有人...