有n片晶元,其中好晶元比壞晶元至少多1片,現需要通過測試從中找出1片好晶元。測試方法是:將2片晶元放到測試台上,2片晶元互相測試並報告測試結果:「好」或者「壞」。假設好晶元的報告是正確的,壞晶元的報告是不可靠的(即對於被測試的晶元顯示的報告可能是壞或者好)
。請設計乙個演算法,使用最少的測試次數來找出1片好晶元。
測試函式可以採用以下方法。
#include
#include
#include
//建立測試函式,引數i表示主動測試晶元, ib表示被測晶元.返回值為被測晶元的測試值
//值為1時表示好晶元,為0時表示壞晶元.
//應用隨機數來表示不確定的值1、0.注意:在主函式中加上隨機數種子語句srand(time(null));
//演算法的輸入可以用陣列表示,比如:abc[17]= 表示17個晶元,其中9片好晶元、8片壞晶元。
intx_test
(int ia,
int ib)
本問題採用的主要思想是分治策略。將n片晶元兩兩一組分成 ⌊n2
⌋⌊\frac n 2⌋
⌊2n
⌋(向下取整) 組,每組測試1次,通過第一輪的⌊n2
⌋⌊\frac n 2⌋
⌊2n
⌋ 的測試淘汰一部分晶元,剩下的晶元構成乙個規模較小的子問題進入第二輪。如果測試的晶元不超過3片 (即子問題規模小於等於3)
,並且好晶元比壞晶元至少多1片,那麼只要測試1次就可以找出好晶元。
而上面所說的淘汰規則需要符合好晶元比壞晶元至少多1片的條件,所以採用的淘汰規則是:
結果是情況1(下圖)時,那麼a、b中留1片,丟掉1片;如果時後三種情況,則把a和b全部丟掉。
(在此不做證明) 情況
a報告b報告結論1
b是好的
a是好的
a,b都好或a,b都壞
2b是好的
a是壞的
至少1片是壞的
3b是壞的
a是好的
至少1片是壞的
4b是壞的
a是壞的
至少1片是壞的
具體演算法思想步驟:
1、晶元數 n 等於2時,根據前面提的條件兩片必然是好晶元,任取一片即可。
2、晶元數 n 等於3時(兩好一壞),任取兩片晶元做測試,若是情況2或3,沒測的那個晶元必定時好晶元;若是其他情況,兩個被測晶元必然是好晶元,則任取一片被測晶元即可。
3、晶元數 n 大於3時,分為兩種情形i。n 為偶數時,晶元兩兩測試比較,在結果為情況1中取出一片另放,以便後續繼續比較,若結果是情況2或3或4的都捨去(就是上面的淘汰規則)。n 為奇數時,取出一片晶元,然後將該晶元和其餘的晶元進行一一比較,若比較結果為情況1的次數 >n2
> \frac n 2
>2n
,則該晶元為好晶元,反之則為壞晶元,將壞晶元刪除後;(此時晶元數為偶數) 接著又回到上面說的 n 為偶數的情形。
c語言:
#include
#include
#include
//建立測試函式,引數ia表示主動測試晶元, ib表示被測晶元.返回值為被測晶元的測試值
//值為1時表示好晶元,為0時表示壞晶元.
intx_test
(int ia,
int ib)
inttest
(int ab,
int n)
if(itmp>=dm)
return iback[k-1]
;}for(i=
0;ik=ic;}if
(k==3)
if(!x_test
(ab[iback[0]
],ab[iback[1]
])||!
x_test
(ab[iback[1]
],ab[iback[0]
]))return iback[2]
;return iback[
rand()
%2];
if(k==2)
return iback[
rand()
%2];
return iback[0]
;}void
main()
;//17
srand
(time
(null))
;int in,i1,i2;
in=test
(abc,17)
;printf
("最少的測試次數為:%d"
,in)
;}
演算法導論 晶元檢測問題之個人看法
寫在問題之前 第一次是在演算法導論裡看到這個問題,當時毫無頭緒,只能在網上尋找思路。檢視了幾個技術部落格,給出了結論,但是在第二個問題的關鍵問題上沒有給出證明,可能大家都覺得這個顯而易見,但是我覺得很難理解。後來我更是花了兩個小時的時間去理解這個結論,現整理給那些同樣困惑的初學者 第乙個和第三個問題...
分治演算法 眾數問題
problem description 給定含有n個元素的多重集合s,每個元素在s 現的次數稱為該元素的重數。多重集s中重數最大的元素稱為眾數。例如,s 多重集s的眾數是2,其重數為3。對於給定的由n 個自然數組成的多重集s,計算s的眾數及其重數。如果出現多個眾數,請輸出最小的那個。input 輸入...
眾數問題 分治演算法
給定含有n個元素的多重集合s,每個元素在s 現的次數稱為該元素的重數。多重集s中重數最大的元素稱為眾數。例如,s 多重集s的眾數是2,其重數為3。對於給定的由n 個自然數組成的多重集s,計算s的眾數及其重數。如果出現多個眾數,請輸出最小的那個。input 輸入資料的第1行是多重集s中元素個數n n ...