放苹果
链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1222
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
把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<cstdio> #include<cstring> using namespace std; int m,n,ans; int a[15]; void dfs(int s,int k,int last){ if(!s){ ans++;return; } if(k>n)return; for(int i=last;i<=s;i++) { a[k]=i; dfs(s-i,k+1,i); } } int main(){ int t; cin>>t; while(t--) { ans=0; memset(a,0,sizeof(a)); cin>>m>>n; dfs(m,1,1); cout<<ans<<endl; } }
法二:递推,f[m][n]表示m个苹果放n个盘子的方案数,每个苹果可以选择放或不放,得到转移方程:
f[m][n]=f[m-1][n-1]+f[m-n][n];
边界:f[m][n]=f[m][m](m<n);f[m][1]=1;
#include<iostream> #include<cstdio> using namespace std; int f[11][11]; int main(){ int t; cin>>t; for(int i=0;i<=10;i++) for(int j=0;j<=10;j++) { f[i][j]=1; if(j==1||!j)f[i][j]=1; else if(i>=j)f[i][j]=f[i][j-1]+f[i-j][j]; else f[i][j]=f[i][i]; } while(t--){ int n,m; cin>>n>>m; cout<<f[n][m]<<endl; } }