P2386 放苹果(排列组合问题)

目录

DP

DFS


题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

扫描二维码关注公众号,回复: 5396049 查看本文章

输入输出样例

输入样例#1: 复制

1
7 3

输出样例#1: 复制

8

输入样例#2: 复制

3
3 2
4 3
2 7

输出样例#2: 复制

2
4
2

这题和数的划分做法相近,可以用DFS和DP,但是要注意该题的盘子是可空的。

DP

F[ i ][ j ]表示将 i 份分在 j 个盘子里

F[ 0 ][ j ]=F[ 1 ][ i ]=1 当苹果数量为0或1时只有一种方法

F[ i ][ 1 ]=1 当只有一个盘子时只有一种方法

  • 当 i<j 时,也就是苹果数量小于盘子数量时,F[ i ][ j ]=F[ i ][ i ]    因为 i 个苹果最多只能占用 i 个盘子 
  • 当i>=j时,F[ i ][ j ]=F[ i-j ][ j ] + F[ i ][ j-1 ] 

F[ i ][ j-1 ] 表示j个盘子中有空盘,取出空盘

F[ i-j ][ j ] 则是每个盘子先放一个苹果的策略


代码:

#include<bits/stdc++.h>
using namespace std;
int f[15][15];//f[i][j]即为i个苹果放在j个盘子里的方案数 
int m,n,ans;
int main()
{
	ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--)
    {
        cin >> m >> n;
        ans=0;
        memset(f,0,sizeof(f));//清空f数组 
        for(int i=1;i<=n;i++)
            f[0][i]=f[1][i]=1;
        for(int i=1;i<=m;i++)
            f[i][1]=1;]
        for(int i=2;i<=m;i++)
            for(int j=2;j<=n;j++)
                if(i<j)//如果苹果比盘子还少 
                    f[i][j]=f[i][i];//等于i个苹果放在i个盘子里 
                else
                    f[i][j]=f[i-j][j]+f[i][j-1];//对于每一次,有两种做法: 
        //1:j个盘子里都放 1个,即 f[i-j][j]
        //2:都不放,即            f[i][j-1]
        cout << f[m][n] << endl;//输出 
    }
    return 0;
}

DFS

#include<iostream>
using namespace std;
int t,n,k;
int f[11][11];
int sum;

void dfs(int step,int num,int tar)
{
	if(tar==1)
	{
		sum++; return ;
	}
	for(int i=step;i<=num/tar;i++)
		dfs(i,num-i,tar-1);
}

int main()
{
	ios::sync_with_stdio(false);
	cin>>t;
	while(t--)
	{
		cin>>n>>k;
		sum=0;
		dfs(0,n,k);//因为可以有空盘,所以从0开始 
		cout<<sum<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40663810/article/details/87696482