我們先來看看題目:
erin買了不少雞蛋,她發現一天吃不完這麼多,於是決定把n個同樣的雞蛋放在m個同樣的籃子裡,允許有的籃子空著不放,請問共有多少種不同的放法呢?第一次接觸這種題目,大家最頭疼的應該是例如(1, 2, 1)和(1, 1, 2)一樣的重複問題,如何解決重複問題,是該題的一大難點。注意:2,1,1和1,2,1 是同一種分法。
input 第一行是測試資料的數目t(0 <= t <= 20)。以下每行均包含二個整數m和n,以空格分開。1<=m,n<=10。
output 對輸入的每組資料m和n,用一行輸出相應的結果。
例如:input:
3 84 7
2 44 2
output:
(注意結尾有換行)
我說說我的思路。
根據題意我們可以大概分成三種情況:雞蛋數目多於籃子數目,雞蛋數目等於籃子數目,雞蛋數目少於籃子數目。
首先,我們來看看最簡單的一種情況:雞蛋數目少於籃子數目。
很明顯,雞蛋少的時候就算每個籃子都放乙個雞蛋,必定會有籃子放不滿,因此我們很容易就可以將這種情況簡化成為:將n個雞蛋放入m個籃子(n <m)。
然後,我們再來看看另外一種情況:雞蛋數目多於籃子數目
雞蛋數目多於籃子數目時,很顯然每個籃子都可以放滿,當然也可以只有乙個籃子放滿,但是再放雞蛋的過程中,很容易發生重複的情況,這時候我們不妨這樣思考:
假設共有m個籃子,n個雞蛋。現在我們先假設m個籃子都放滿且每個籃子都只放乙個雞蛋,放入雞蛋後剩下的雞蛋數目為n-m,再讓剩下的n-m去放m個籃子,此時我們不繼續往下討論。再假設m-1個籃子都只放滿乙個雞蛋,與前面同樣的道理,我們可以得到讓n-(m-1)個雞蛋放m-1個籃子……這樣乙個個增加空籃子的數目直到非籃子數目為2或1。
為了更清楚地說明這種原理,我們設乙個放雞蛋函式為f(m, n) (m為籃子數目,n為雞蛋數目),然後我們引用例子中m= 4, n= 7,我們就可以進行拆分:
f(4,7)= f(4, 3)+f(3, 4)+f(2, 5)+f(1, 6)我們發現當籃子數目m= 2或m= 1時, 分類數目是顯而易見的當m= 1時, f(1,n)= 1; 當m= 2時,f(2, n)= n/2(當n為奇數取整)(注意當籃子數目為2時要求兩個籃子都放,不存在乙個籃子不放的情況)。於是我們得到f(3, 1)= 1, f(2, 2)= 1, f(1, 3)= 1, f(1, 4)= 1, f(2, 3)= 1,f(1, 6)= 1。= [f(3, 3)]+[f(3, 1)+f(2, 2)+f(1, 3)]+[f(1, 4)+f(2, 3)]+[f(1, 6)]
=[f(3, 3)]+[f(1, 1)+f(2, 2)+f(1, 3)]+[f(1, 4)+f(2, 3)]+[f(1, 6)]
我們現在還不知道f(3, 3)的值。
所以我們必須討論最後一種情況:雞蛋數目等於籃子數目。
如果按照之前的拆分方式,我們可以將f(3, 3)拆分為:
f(3, 3)= f(3, 0)+ f(2, 1)+ f(1, 2)= f(3, 0)+ f(1, 1)+ f(1, 2)根據上述的方法我們很快就得到 f=f(2, 1)=f(1, 1)= 1, f(1, 2)= 1。但是我們不知道怎麼求f(3, 0)。
為了搞清楚發f(3, 0)是什麼,我們認真思考將3個雞蛋放3個籃子的情況:3個籃子放都各放1個雞蛋;1個籃子放1個雞蛋,乙個放2個,另乙個不放;3個雞蛋都放進1個雞蛋,另外兩個不放。我們發現1個籃子放1個雞蛋,乙個放2個,另乙個不放的情況對應於f(2, 1)即f(1, 1),3個雞蛋都放進1個雞蛋,另外兩個不放的情況對應於f(1, 2),剩下的3個籃子放都各放1個雞蛋的情況只能對應於f(3, 0)。這樣我們就知道f(3, 0)= 1。所以
f(3, 3)= f(3, 0)+ f(2, 1)+ f(1, 2)= f(3, 0)+ f(1, 1)+ f(1, 2)=1+1+1=3類似我們試著去求f(4, 4),我們同樣發現f(4, 0)= 1。所以根據不完全歸納,我們可以推出f(m, 0)= 1。
現在再回到之前的例子。
f(4,7)= f(4, 3)+f(3, 4)+f(2, 5)+f(1, 6)很明顯這就是例子給出的結果。= [f(3, 3)]+[f(3, 1)+f(2,2)+f(1, 3)]+[f(1, 4)+f(2, 3)]+[f(1, 6)]
=[f(3, 3)]+[f(1, 1)+f(2, 2)+f(1, 3)]+[f(1, 4)+f(2, 3)]+[f(1, 6)]
= 3+1+2+1+1+1+1+1=11
如果我們將這種方法轉化為**時,我們要實現這種拆分,我們必須用到遞迴,注意寫**時將基本情況交代清楚,否則程式將出現錯誤。
我寫的**如下:
#include
int main()
for (i= 0; i< number; i++)
}int way= 0;
int put(int basket, int egg)
way= 0;
way+= sum;
}//進行拆分並對遞迴結果進行累加
} }
else
if (basket> egg) put(egg, egg);
//雞蛋數目少於籃子數目的情況
else
way= sum;
} return way;//輸出最終結果
}
另外附上標答的**,用的就是我的方法,但標答的**更簡潔
#include
int egg(int
m, int n);
int main()
return
0; }
int egg(int
m, int n)
放雞蛋問題
description把m 個同樣的雞蛋放在 n個同樣的籃子裡,允許有的籃子空著不放,問共有多少種不同的放法?用 k表示 5,1,1和 1,5,1是同一種分法。input 第一行是測試資料的數目t 0 t 20 以下每行均包含二個整數m和 n,以空格分開。1 m n 10。output 對輸入的每組...
雞蛋樓層問題
一 n層樓2個雞蛋問題 題目描述 有兩個軟硬程度一樣但未知的雞蛋,它們有可能都在一樓就摔碎,也可能從一百層樓摔下來沒事。有座100層的建築,要你用這個雞蛋通過最少的次數確定哪一層是雞蛋可以安全落下的最高位置。可以摔碎兩個雞蛋。分析 看到這個題目,最保險的方法就是從第一層往上一層一層試驗,但這樣就需要...
扔雞蛋問題
因為就乙個雞蛋,所以,我們很容易就可以想到從第一層開始扔就可以了,直到碎,說明這是n 1層。這裡當然也可以按照第乙個問題的方法來實現,即從第一層開始向上,直到摔碎為止,但是這種方法顯然是低效的。方法二 二分查詢 當時就想到了使用這種方法,即採用二分查詢的思路,第一次在50層扔 如果碎了,那麼從第一層...