递归--放苹果
問題描述
把 M 個(gè)同樣的蘋果放在N 個(gè)同樣的盤子里,允許有的盤子空著不放,問共有多少
種不同的分法?(用K 表示)注意:5,1,1 和1,5,1 是同一種分法。
輸入數(shù)據(jù)
第一行是測試數(shù)據(jù)的數(shù)目t(0 <= t <= 20)。以下每行均包含兩個(gè)整數(shù)M 和N,以
空格分開。1<=M,N<=10。
輸出要求
對(duì)輸入的每組數(shù)據(jù)M 和N,用一行輸出相應(yīng)的K。
輸入樣例
1
7 3
輸出樣例
8
我的思路:因?yàn)轭}目是用遞歸做的。我就想如何可以原來問題分解了一個(gè)更小的問題,又因?yàn)楸P子都一樣的。先考慮第一個(gè)盤子放蘋果的情況,然后遞歸的考慮后面的各種情況,為了必要重復(fù),我還設(shè)定了他們放蘋果的數(shù)量是遞減的。同時(shí)還要考慮N>M的情況其實(shí)和N=M的情況是一樣的。于是我就寫出了這個(gè)四不像的算法。我也不知道是什么東西,但是能出結(jié)果,還能AC。。。哈哈。?
后來想想,我的方法有點(diǎn)像是搜索的方式,DFS(Depth first search)。即我先把前面我說的那些條件(按蘋果數(shù)遞減放)設(shè)定好,然后DFS去搜索每個(gè)盤放蘋果的情況,當(dāng)剩下最后一個(gè)盤的時(shí)候,就能得到一種情況。
#include <stdio.h>
int M,N,nSum;
void recursion(int nCount,int left,int prio)
{
??? int i;
??? if (nCount == N-1 )
??? {
??????? if (left <= prio) ?
??????? {
??????????? nSum++;
??????? }
??? }
??? else
??? {
??????? for (i =prio; i >= 0; i--)
??????? {
??????????? if (i <= left)? //當(dāng)前的值必須小于剩下的蘋果數(shù)
??????????? {
??????????????? recursion(nCount+1,left-i,i);
??????????? }
??????? }
??? }
}
int main()
{
??? int t;
??? scanf("%d",&t);
??? while (t)
??? {
??????? t--;
??????? nSum=0;
??????? scanf("%d%d",&M,&N);
??????? if(N > M) N=M;
??????? recursion(0,M,M);
??????? printf("%d\n",nSum);
??? }
??? return 0;
}
其實(shí)真正的遞歸是這樣的,考慮兩種情況:
- 每個(gè)盤都放有蘋果。即每個(gè)盤已經(jīng)放有蘋果,這時(shí)的情況和把剩下m-n個(gè)蘋果放到n個(gè)盤的情況是一樣的,f(m-n,n);
- 至少有一個(gè)盤不放蘋果。即把m個(gè)蘋果放到n-1個(gè)盤子。f(m,n-1);
當(dāng)然必須考慮m<n時(shí),此時(shí)和f(m,m)的情況是一樣的。
最后判斷程序的出口:當(dāng)蘋果數(shù)量為0或者盤數(shù)只剩1那么就表明找到一種情況。
#include <stdio.h>int recursion(int m, int n)
{
??? if (m == 0 || n == 1) return 1;
??? if (m < n) return recursion(m,m);
??? return recursion(m,n-1) + recursion(m-n,n);
}
int main()
{
??? int m,n,t;
??? scanf("%d",&t);
??? while (t)
??? {
??????? t--;
??????? scanf("%d%d",&m,&n);
??????? printf("%d\n",recursion(m,n));
??? }
??? return 0;
}
/5/15 22:18
/5/15 22:18
總結(jié)
- 上一篇: 113道C语言题目
- 下一篇: 递归--整数划分问题