約瑟夫斯問題及其程式設計

2021-06-14 05:09:09 字數 1972 閱讀 7775

然後問題是,給定了n和k,一開始要站在什麼地方才能避免被處決?

在約瑟夫斯問題裡詳細介紹了其中k=2時此問題的數學方式的解法,並得到了乙個可以通過數學歸納法證明的定理:

如果比較令人眼前一亮的是這個結論的表現形式竟與整數n的二進位制表示有關:即把n

的第一位移動到最後,便得到

的二進位制表示為

接著使用動態規劃的方法得到一般情況下(即

當n=1時,

但n>1時,

#include using namespace std;

int josephus(int n, int k);

int main()

int josephus(int n, int k)

}

當輸入n=9、k=5時最後乙個數是8,下圖就是執行的結果:

注意:這裡必須要對josephus(n, k)的值進行判斷,因josephus(n-1, k)+k>=k>0,所以當josephus(n, k)為0時,必須要將其賦值為n。(為什麼是n而不是n*m?其中m是大於1的任意正整數)

例如注釋掉上述**中的這段**:if(0 == ret) ret = n;

執行的結果如下所示:

此時結果是錯誤的,最後留下來的人應該是9才對。

同時這裡的遞推可以用迴圈來實現:

#include using namespace std;

int main()

cout << "the final winner is " << ret << endl;

system("pause");

return 0;

}

執行結果如下圖所示:

這裡解決這個問題的核心步驟(即程式的基本演算法)是:

1)建立乙個具有n個鏈結點而無頭結點的迴圈鍊錶;

2)確定第乙個報數人的位置即m;

3)不斷地從該鍊錶中刪除報數人處的鏈結點,直到該鍊錶為空。

其**如下:

#include using namespace std;

typedef struct node

node;

void createlist(node* &head, node* &tail, int n);

void print(node* &head);

void countprint(node* &head, node* &tail, int k);

int main()

void createlist(node* &head, node* &tail, int n)

head = new node;

head->data = 1;

head->next = null;

node *p = head;

for(int i = 2; i < n+1; i++)

tail = p;

p->next = head;

}void print(node* &head)

while(p != head);

cout << "\n";

}void countprint(node* &head, node* &tail, int k)

else

}if(cur == cur->next)

}

執行結果如下圖所示:

約瑟夫斯問題

有n個人圍成一圈,報數從1到m依次迴圈報數,報到m的就退出 死 現在我們來看遞推,由於為了方便表示 s m i 0的情況,我們讓第一人的編號為0,從一開始也可以 既然你問遞推,那步驟就不說了,只說這個公式吧 讓獲勝者的編號為0 最後乙個人只有他了當然是0 f i 表示獲勝者在剩下i個人時的那一局的編...

約瑟夫斯問題 關於約瑟夫斯問題的反饋

約瑟夫斯問題 我上週的文章是關於解決kotlin的約瑟夫斯問題的。為了便於比較,這是我最初編寫的版本 class soldier val position int fun isdead state state dead enum class state class circle private va...

約瑟夫問題及其變形

問題 n個數排乙個圈,從編號1開始刪除,以後每m個數刪一次,問最後乙個被刪除的數。2 n 10000,1 k 10000 includeusing namespace std int main return 0 變形 從第k個數開始刪。includeusing namespace std defin...