放苹果

51 篇文章 0 订阅
12 篇文章 0 订阅
Language:
放苹果
Time Limit: 1000MS Memory Limit: 10000K
   

Description

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8

Source


#include <iostream>     //首先,使用递归的思想解决该问题

using namespace std;

int f(int m,int n)
{
    if(n>m)
        n=m;
    if(n==1||m==1||m==0)
        return 1;
    return f(m,n-1)+f(m-n,n);     //对于m个苹果放在n个盘子里,可以分成两种情况:m个放在n-1个盘子里;m-n个放在n个盘子里。
}                                 //解释一下后者,后者实际解决的是,n个盘子中至少有一个苹果的情况,那每个盘子减去一个之后,就变成了m-n个苹果放在n个盘子里的情况了。
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m,n;
        cin>>m>>n;
        cout<<f(m,n)<<endl;
    }
    return 0;
}

#include <cstdio>
#include <cstring>
#include <iostream>   //介绍dp的解法
using namespace std;
int dp[11][11];
int f1(int m,int n)// 记忆化dp,该解法思路同递归,由递归的思想推出状态转移方程。
{
	if(m<0)
        return 0;
	if(dp[m][n])
	    return dp[m][n];
	if(n==1||m==0)
	    return 1;
	dp[m][n]=f1(m-n,n)+f1(m,n-1);
	return dp[m][n];
}
void f2(int m,int n)//背包dp,
{
	int i,j,k;
	int dp[11][11]={0};
	dp[0][0]=1;
	for(i=0;i<=m;i++)//多组
		for(j=1;j<=n;j++)
			for(k=i;k<=m;k++)//多重
				dp[j][k]+=dp[j-1][k-i];
	cout<<dp[n][m]<<endl;
}
void f3(int m,int n)//f3中dp[i][j]表示i个苹果放入j个箱子,且每个箱子至少放一个的种数
{
	int i,j;
	int dp[11][11]={0};
	dp[0][0]=1;
	for(i=1;i<=m;i++)
		for(j=1;j<=i;j++)
			dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
	int ans=0;
	for(i=1;i<=n;i++)
		ans+=dp[m][i];
	cout<<ans<<endl;
}
void f4(int m,int n)//f4中dp[i][j]表示i个苹果放入j个箱子,但每个箱子可以为空的种数
{
	int i,j;
	int dp[11][11]={0};
	for(i=0;i<=n;i++)
        dp[0][i]=1;
	for(i=0;i<=m;i++)
	    dp[i][1]=1;
	for(i=1;i<=m;i++)
		for(j=1;j<=n;j++)
			dp[i][j]=dp[i][j-1]+((i-j>=0)?dp[i-j][j]:0);
    cout<<dp[m][n]<<endl;
}
int main()
{
	int cas,m,n;
	cin>>cas;
	while(cas--)
    {
		cin>>m>>n;
		memset(dp,0,sizeof(dp));
		//cout<<"Case f1:";
		cout<<f1(m,n)<<endl;
		/*cout<<"Case f2:";
		f2(m,n);
        cout<<"Case f3:";
        f3(m,n);
        cout<<"Case f4:";
        f4(m,n);*/
	}
	return 0;
}

#include <iostream>
#include <string>            //这是DFS方法

using namespace std;

int t,n,m,s;
int num[11];

void dfs(int x,int y)
{ 
    if(x==m)
    {
        if(y>=num[m-1])
            s++;
    }     
    else 
        for(int i=num[x-1];i<=y&&(y/(m-x)>=i);i++)
        {
            num[x]=i;
            dfs(x+1,y-i);
        }
}
        
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));      
        scanf("%d%d",&n,&m);
        s=0;
        dfs(1,n);
        printf("%d\n",s);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值