各位朋友新年好!過完年後來csdn逛逛,發現上了新的編程題目,一道罐子和硬幣,一道搜索排序。今天就先說罐子和硬幣的題目。先看題目:
有n個罐子,有k個硬幣,每個罐子可以容納任意數量的硬幣。罐子是不透明的,起初你可以隨機把這k個硬幣任意放在罐子裏。然後罐子被打亂順序,你從外表無法區別罐子。最後罐子被編上號1-n。你有p次機會,每次你可以選擇某個罐子,如果該罐子裏有硬幣,則你可以得到1個(你不可以知道該罐子裏有多少硬幣),如果該罐子是空的,你得不到任何硬幣。你最終要得到至少c枚硬幣,我們的問題是給定n,k,c,求出最少的p,存在一種你最初放硬幣的方式,無論罐子如何被打亂順序,你都能p次機會內獲得至少c個硬幣。
輸入n,k,c (0 < n <=1000000, 0 < c <= k <=1000000)。
輸出,最小的p值。
例如n = 3, k = 6, c = 4。 你可以把每個罐子放入兩個硬幣,這樣得到4次機會可以得到4個硬幣,輸出4。
題目看起來挺簡單的,仔細想想似乎又不簡單。
分析:這道題其實對編程考察的不多,主要是考察思維方式。即你如何放硬幣,如何取硬幣的方式。
我最開始是這麼想的,把硬幣平均放在每個瓶子裏面,取硬幣的時候,每個瓶子輪流取。直到取到c個,問題是,平均放,可能有些瓶子裝的少一個,即k%n !=0,比如說n=10,k=28,那麼每個瓶子裝2個,還有8個瓶子多裝一個,裝了3個,如果我們要取25個,即c=25,前20個比較好取,後5個怎麼取?按照這種裝法,至少還要取2+5=7次,因爲有2次你可能摸到的是空瓶子。但是這種取法是不是最優了?如果k=21,c=21了?那不是要取20+1+9=30次。顯然,我們可以吧最後一個瓶子裏面的兩個金幣放到前面不是3個金幣的瓶子裏面,這樣取得次數就少於30,再依次移動最後一個瓶子裏面的金幣到前面不是3個金幣的瓶子,使其金幣數達到3個,我們發現,次數都會逐漸減少,直到不能移動爲止。
現在回過頭來看下,這道題基本上思路就比較清晰了。
步驟
1、首先將硬幣平均分配到每個瓶子,如果k%n==0,那麼取c個硬幣只需要c次。
2、如果k%n !=0 ,那麼我們就要考慮要取多少個硬幣,如果c<Math.Floor(k/n)*n,很顯然平均分配硬幣,然後輪流取每個瓶子,c次就可以取到了。
3、當k%n !=0 時,而c>=Math.Floor(k/n)*n的時候,也就是我們上面分析的,這個時候就要從最後一個瓶子開始抽取硬幣,補充到前面沒有裝滿的瓶子。
這個如果用畫圖的方式展現,就很好理解了:
瓶1,瓶2,............瓶n
1,1,1,1,。。。,1
1,1,1,。。。。。1
。。。。。。。。
1,1,。。,0,0.。0
首先平均分配,發現後面還有n-k%n個瓶子少一個硬幣,因此,吧最後一個瓶子裏面的硬幣拿出來補充這(n-k%n +1)個瓶子裏,不足,就再下一個瓶子裏的硬幣,最後形成了這樣一個圖:
瓶1,瓶2,............瓶n
1,1,1,1,。。。1...0
1,1,1,。。。。1...0
。。。。。。。1...0
1,1,。。, 1,0...0
其中行數row = k / n + 1;
而這n個瓶子中有col=k/row 個瓶裝的一樣多,剩下的瓶子,要麼全爲空,或者有一個吧剩下的硬幣裝進去了,很顯然,這時候要取c個硬幣,最差的情況p= n - col + c;
ok,到此分析完畢了,也就是三種情況,代碼也非常的少,大概十多行吧,提交,沒問題,通過。