题目链接~~>
这题开始用搜索过了,但是看别人代码用递归而且比搜索时间短,还可以用dp和母函数做。
方法一:
递归思想:
递推代码:
#include<stdio.h> int f(int m,int n) { if(m==1||n==1)//当只有一个苹果或一个盘子时就剩下一种办法 return 1; if(m<n) //如果盘子多,苹果少,按苹果数进行分配 return f(m,m); else if(m>n) //当苹果大于盘子的时候,按空一个盘和每个盘子都放一个开始递归 return f(m,n-1)+f(m-n,n); else //当盘子数和苹果个数一样多时,每个盘子放一个是一种,加上空一个盘子 return 1+f(m,n-1); } int main() { int t,m,n; scanf("%d",&t); while(t--) { scanf("%d%d",&m,&n); printf("%d\n",f(m,n)); } return 0 ; }
方法二:
DP思想:先不考虑空盘子的情况,因为加上一个空盘子和加上多个空盘子是一样的结果。先考虑每个盘子都有苹果的情况。例如:五个苹果放进两个盘子里。1.可以每个盘子里先放一个苹果,那就相当于三个苹果放进两个盘子里;2.可以让先将其中一个盘子里放一个,再将剩下的放进剩余的盘子里。最后五个苹果放进二个盘子了就相当于五个苹果放进一个盘子里的情况(给它加上一个空盘子,就相当于两个盘子)加上五个苹果放进两个盘子。
方程:a[ i ][ j ] = a[ i-1 ][ j-1 ]+a[ i-j ][ j ] ;
代码:
#include<stdio.h> #include<string.h> int main() { int T, n, m, i, j, ans, a[15][15]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); a[1][1] = 1; for(i = 2; i<=n; i++) for(j = 1; j<=i; j++) a[i][j] = a[i-1][j-1]+a[i-j][j]; ans = 0; for(i = m; i > 0; i--) ans+=a[n][i]; printf("%d\n",ans); } return 0; }