做題感悟:放蘋果
阿新 • • 發佈:2018-11-26
其實,這道題在一開始我就想到了正確解法的一部分,但是因為某閆同學而否定了自己(畢竟只想到了一部分)。
好的我們先來看一下這道題:
放蘋果
- 總時間限制:
- 1000ms
- 記憶體限制:
- 65536kB
- 描述
- 把M個同樣的蘋果放在N個同樣的盤子裡,允許有的盤子空著不放,問共有多少種不同的分法?(用K表示)5,1,1和1,5,1 是同一種分法。
- 輸入
- 第一行是測試資料的數目t(0 <= t <= 20)。以下每行均包含二個整數M和N,以空格分開。1<=M,N<=10。
- 輸出
- 對輸入的每組資料M和N,用一行輸出相應的K。
- 樣例輸入
- 1
- 7 3
- 樣例輸出
- 8
- 好的,先說一下我一開始想到的:
- 首先,這道題是一個十分典型的遞迴題,至於為什麼我就不說了,你們都知道。因此,先找到這道題的出口:當僅剩一個盤子(所有剩的蘋果都放在一個盤子裡)或沒有蘋果(所有盤子都空)時,都只有一種可能。因此,將f(m)拆分開成f(m-1)+n,依次遞迴下去。
- 很顯然,這並不成立
- 比如:如果有盤子不放蘋果呢?
- 好吧,不賣關子了,直接說正確思路:
- 首先,遞迴出口已經找到,那麼下一個目標就是拆分可能性,依次遞迴,直到滿足出口條件(m==0||n==1)時遞歸回來。
- 那麼,可能性如何拆分呢?
- 我們知道對於m個蘋果,只有兩大類情況:每個盤子都有和有空盤子。那麼我們是不是可以拆分f(m,n)=f(m-n,n)+f(m,n-1)呢?
- 顯然成立
- 但是,細心的朋友會發現:當m<n時,m-n居然成了負數
-
?!
- 原因是:當蘋果數小於盤子數時,你居然還要求人蘋果把盤子填滿?這很顯然是錯誤的。所以我們就可以將問題轉化為m個蘋果放在m個盤子中(題目中說過順序不重要),因此,我們要加一個特判。
- 好的,我講完了?
- 並沒有!
- 補充一句:當m<n時,你覺不覺得接下來就會到達一個出口呢?
- 好吧,這並不重要。。。
- 最後,附上本題程式碼
#include<cstdio> using namespace std; int fang(int m,int n) { if(m==0||n==1) { return 1; } else if(m<n) { return fang(m,m); } else { return fang(m-n,n)+fang(m,n-1); } } int main() { int t,M,N; scanf("%d",&t); for(int i=1; i<=t; i++) { scanf("%d%d",&M,&N); printf("%d\n",fang(M,N)); } return 0; }