1.約瑟夫問題:n個人編號為0...n-1.圍成乙個圈。從編號為0的人開始順時針計數,每數到k個人時讓其出局(第一次出局的是編號為(k-1)mod n的人),接著又從下乙個人開始計數。經過n-1輪報數後,求最終留下的人的編號。
我們只關心最後乙個留下的人,比如,當刪除第乙個人後,也就是刪除編號為(k-1)mod n的人,此時我們要求的人就是剩下n-1個人中最後留下的那個人。用f[i]表示有 i 個人圍成的圈中最後剩下的人的編號,當刪除第 1 個人後,我們將原序列重新編號,從原來編號為 k 的開始一次編號 0...i-2,根據原問題的定義,此時f[i-1] 表示剩下的 i-1 個人最後順下的那個人的編號。那麼f[i-1]與f[i]的號碼相差乙個 k ,注意得取模。於是得到遞推式:
f[ i ]=(f[i-1]+k) mod i; f[1]=0;
#includeusing namespace std;
#define max_size 10001
int jos[max_size];
int main()
return 0;
}
顯然從遞推公式可知,時間複雜度為o(n),空間複雜度也為o(n).
2.約瑟夫變形問題:同樣是編號從0...n-1的 n 個人圍成乙個圈,從編號為0的人開始計數,第一次刪除第 1 個人(編號為 0的人),接著從刪除的人的下乙個人開始計數,數到2個人時刪除(刪除下標為2的人),....依次類推,第k次數k個人,刪除數到k的人。求經過n-1輪後最後留下的那個人。
此時和剛才不同的是,每次報數不是固定的數k,從而f[i]還需要增加一維來表示這種狀態。設f[i,j]表示編號為 0...i-1的 i 個人中依次隔 j ,j+1,j+2...j+i-2個人刪除最終留下人的編號:則在f[i,j]中刪除的第乙個人編號是j-1,接著從編號為j的人開始從新編號 0...i-2.接著是隔j+1...j+i-2個人刪除,於是可以記為f[i-1,j+1],而現在的標號與原來編號相差 j ,同樣要取模。
於是f[i,j]=(f[i-1,j+1]+j) mod i;初始化 f[1,0....n]=0; 我們最終求的是f[n,1].時間空間複雜度都是o(n^2)
#includeusing namespace std;
#define n 5001
int jos[n][n];
int main()
} cin >> t;
while (t--)
return 0;
}
約瑟夫問題及其變形
問題 n個數排乙個圈,從編號1開始刪除,以後每m個數刪一次,問最後乙個被刪除的數。2 n 10000,1 k 10000 includeusing namespace std int main return 0 變形 從第k個數開始刪。includeusing namespace std defin...
變形的約瑟夫環問題
time limit 1 sec memory limit 128 mb submit 142 solved 68 submit status web board n個站成一列的士兵和乙個整數m,士兵編號是1 n。每次士兵按編號從小到大的順序依次報數,如果報的數不是m的倍數,則該士兵出列。這樣重複幾...
UVa 1394 約瑟夫問題的變形
本來是要昨天來寫這學習 的,然後昨晚寢室又斷電了,忍不住在這裡吐槽一下,嗯,寢室天天斷電。題意就是輸入n,k,m三個數,n個數排成乙個圈,第一次刪除m,以後每數k個數刪除一次,求最後乙個被刪除的數。言歸正傳,以前寫過乙個鍊錶的約瑟夫問題,但是在這裡肯定是會超時的。後來看了些參考,終於明白了怎麼做。把...