历年上机题---放苹果

题目描述

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

输入描述:

每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

输出描述:

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

nowcoder.com/practice/4f0c1e21010e4d849bde5297148e81d9?tpId=61&tqId=29513&tPage=1&ru=/kaoyan/retest/1002&qru=/ta/pku-kaoyan/question-ranking

思路:假设有7个苹果,3个盘子。

那么可以这样尝试这样划分: 0+ 7  (只用了一个盘子)

                                                1+ 6 (用了两个盘子)

                                                2+ 5  (用了两个盘子)

                                                3+ 4     (用了两个盘子)

现在思考,如果用3个盘子,有哪些划分方法?

考虑将(1+6)在进行划分,即将装有6个苹果的盘子,分出一部分。可以有 1+5,2+4,3+3

即(1,1,5),(1,2,4),(1,3,3)。其实从这里我们可以找到一些动态规划的思路,如果我们已经计算出将6个苹果装在两个盘子,有多少种方法,那么,就可以很快的得出,将7个苹果分成3盘,其中1盘有1个的方法数。

同理,也可以继续分析(2+5).....

设dp[i][j]为i个苹果,放入j个盘子(其中可以有盘子为空)的方法数。

1. dp[0][j] =1 (因为已经没有苹果了)

2. 如果n>m,那么其实只要计算dp[m][m]即可,因为肯定有盘子空着

3. dp[i][j]= dp[i-j][j] + dp[i][j-1]  (它的意思是:如果我有i个苹果,j个盘子。那么我可以这么选,要么把每一个盘子都至少放一个,即先拿出j个苹果。要么我空着一些盘子(其实你空着1个盘子,这样递归下去,就可以实现空着多个盘子。))

代码:

记忆化搜索或者递推都可以

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int dp[20][20];
int dfs(int m,int n)
{
    if(m==0) return 1;
    if(n==1) return 1;
    if(dp[m][n]!=-1) return dp[m][n];
    if(n>m) return dp[m][n]=dfs(m,m);
    return dp[m][n] = dfs(m-n,n)+dfs(m,n-1);
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(dp,-1,sizeof(dp));
        cout<<dfs(m,n)<<endl;
    }
    return 0;
}
发布了449 篇原创文章 · 获赞 197 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/105427868