今天在乙個oj上做了乙個joseph problem(解約瑟夫問題)的題,題目不難,直接用迴圈鍊錶模擬實際操作即可完成,但是用此種方法的時間太長,超時,所以我就用了乙個大家對這類問題比較常用的解法——數學方法。
題目內容:
實作joseph problem.
假設一開始有n個人,編號1~n,
按照順序以順時針圍成乙個圓圈。
遊戲開始時,編號1的人拿刀。
之後每一輪刀子會被往下傳m個人,
而當輪最後拿到刀子的人會將他的下乙個人殺掉,
殺完後刀子會再傳給被殺的下乙個人。
這樣一輪就算結束。
遊戲會進行許多輪,直到只剩下最後乙個人。
範例1:n=5, m=2
第一輪:刀子傳給3號,4號被殺,刀子再傳給5號 (1 2 3 5)
第二輪:刀子傳給2號,3號被殺,刀子再傳給5號 (1 2 5)
第三輪:刀子傳給2號,5號被殺,刀子再傳給1號 (1 2)
第四輪:刀子傳給1號,2號被殺,最後1號存活。
範例2:n=4, m=3
第一輪:刀子傳給4號,1號被殺,刀子再傳給2號 (2 3 4)
第二輪:刀子傳給2號,3號被殺,刀子再傳給4號 (2 4)
第三輪:刀子傳給2號,4號被殺,最後2號存活。
輸入格式:
輸入第一行為乙個數字t,代表測資的筆數。
接下來會有t筆測資,每一筆測資一行,
會有兩個數字n,m,數字間以空格區隔。
數字範圍:
t < 1000
0 < n <= 1000
0 < m <= 1000
輸出格式:
輸出一行數字,將每筆測資最後存活下來的人的編號加總。
輸入樣例:
35 2
4 38 4
輸出樣例:
4時間限制:1000ms記憶體限制:32000kb
第一點想到的實現演算法就是完全模擬問題中的方法進行演算法設計,**如下:#include int arrq[1000]; //迴圈佇列,此處用固定值
int qcount, head, tail; //佇列操作
void add(int x, int size)else
qcount ++;
}void del(int size)
int main()
while(qcount != 1)
del(n);
} sum += arrq[head]; }
printf("%d", sum);
return 0;
}
此演算法雖然很容易理解,但是時間複雜度是o(nm),執行大佇列時會超時。
這裡先拿乙個經典的例子進行說明。
問題:有n個人站成環 從1開始報數,報k的人出列,之後下乙個人報1,問最後存在的是誰?
這裡設n = 11,k = 3。下面將處理的所有過程寫下來。
最後存在的是7。
這裡可以用 f(n, k)來描述每一輪的操作,n是當前佇列中的人數,k是出列的人,f(n,k) = (f(n - 1,k) + k) % n,下面來實現。
最底端是 f(1,k) f(1,k) = 0 就是說只有乙個人的時候存在者的下標是0,編號是7向上,f(2,k) = (f(1,k) + k) % n = f(2,3)=(f(1,3) + 3) % 2 = 3 % 2 = 1,在只剩兩個人時,存在者在這一輪陣列中的下標位置是1(下標位置為1 編號是7 )
向上,f(3,3) = (f(2,3) + 3) % 3 = 4 % 3 = 1,在只剩三個人時 在存者在這一輪陣列中的下標位置是1 (下標位置為1 編號是7)
向上,f(4,3) = (f(3,3) + 3) % 4 = 4 % 4 = 0……
……最後,f(11,3) = (f(10,3) + 3) % 11 = 6 % 11 = 6 (看看上面的**第一行 下標位置為6 編號是7 )
在只剩三個人時 倖存者在這一輪陣列中的下標位置是0 (看看上面的** 下標位置為0 編號是7 )
通過上述很容易寫出程式來:int fn(int n,int k)
return s + 1; //因為是從陣列下標是從0開始的,所以這裡要加1
}
好了,經典問題說完後,來看一下我們這個題,把這種數學推導出來的公式移植到程式中,如下:#include int main()
sum += s+1;
} printf ("%d", sum);
return 0;
}
這裡的時間複雜度是o(n),所以完勝。
部落格名稱:王樂平部落格
理解 約瑟夫環
總結了個小經驗,有時候光靠看是看不出什麼端倪來的,還必須得動下筆,比劃比劃也許就那麼簡單 include include typedef struct node node node creatlist int n 建立乙個含 n個人的迴圈鍊錶 p next head 構建迴圈鍊錶 return he...
演算法詳解 約瑟夫問題
約瑟夫 josephus 問題 也成為約瑟夫置換 也成為約瑟夫環。n個人圍成一圈 編號1 2 3 n 這些人輪流數數 從編號為1的人開始,從1開始數 當數到m的人就會被處決 接著,後面的人再從繼續從1開始數數 如下下去,知道最後只剩下乙個人為止。問題是給定了n和m,一開始要找到什麼位置才能避免被處決...
JAVA求解約瑟夫環
與前面我們介紹的大多數程式問題一樣,約瑟夫環問題也是來自於乙個故事。這個故事發生在乙個名叫約瑟夫的猶太人身上,據說在羅馬人占領喬塔帕特後,39 個猶太人與約瑟夫及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人 開始報數,每報數到第...