放苹果

放苹果

链接: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;
    }    

}


 
原文地址:https://www.cnblogs.com/EdSheeran/p/7709784.html