分蘋果(列舉加遞迴)
描述:把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
*/
#include <iostream>
#include <fstream>
#include<algorithm>
using namespace std;
int Count;
int a[11];//a[i]表示第i個盤子分的蘋果個數
int sum;
int m,n;
int min(int x,int y)
{
return x<=y?x:y;
}
void Try(int j,int i) //嘗試在剩餘了j個蘋果的情況下給第i個盤子分蘋果
{
if(i>n) return ;
for(int k=min(a[i-1],j);k>=1;k--)
{
a[i]=k; sum=sum+k; //第i個盤子分k個蘋果,sum表示已分蘋果的總數
if(sum==m) //一種分法
{
Count++; //分法數加1
}
else Try(j-k,i+1);
sum=sum-k;
}
}
int main()
{
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>m>>n;
Count=0;
if(n==1) //一個盤子只有一種分法
{
Count=1;
cout<<Count<<endl;
continue;
}
for(a[1]=m;a[1]>=1;a[1]--)
{//列舉第一個盤子分配蘋果的個數
sum=a[1];
if(a[1]==m)
{
Count++;
}
Try(m-a[1],2); //在已知第一個盤子分完蘋果的情況下從第2個盤子開始分蘋果
}
cout<<Count<<endl;
}
return 0;
}
第二種方法:可計算放蘋果方案數也可以輸出每一種放法。
#include <stdio.h>
#include <stdlib.h>
int resu[20];
int f(int m,int n,int x)
{//m個蘋果,n個盤子,且第一個盤子至少放x個蘋果的分法數
int sum=0;
if(n==1)
{
resu[0]=m;//最後一個盤子放m個蘋果
int j=0;
while(resu[j]!=-1) //輸出一種放蘋果方案
{ printf("%d ",resu[j]);j++;}
printf("\n");
return 1; //如果只有一個盤子,分法數為1(遞迴出口)
}
for(int i=x;i<=m/2;i++) //第一個盤子可以放x~m/2個蘋果
{
resu[n-1]=i;
if(m-i>=i) sum+=f(m-i,n-1,i);//保證後分配蘋果的盤子上蘋果數量大於等於前一個盤子蘋果數
}
return sum;
}
int main()
{
int n;
scanf("%d",&n);
int a,b; //蘋果數和盤子數
while(n--)
{
scanf("%d%d",&a,&b);
resu[b]=-1;
printf("%d\n",f(a,b,0));
}
return 0;
}