牛客网HJ61 放苹果

题目

描述
把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
注意:如果有7个苹果和3个盘子,(5,1,1)和(1,5,1)被视为是同一种分法。

数据范围: 0 ≤ m ≤ 10 , 0 \le m \le 10, 0m10, 1 ≤ n ≤ 10 1 \le n \le10 1n10

输入描述:
输入两个int整数

输出描述:
输出结果,int型

示例1
输入:
7 3

输出:
8

递归

递归分析

设m个苹果放入n个盘子的分法为 f ( m , n ) f(m,n) f(m,n),对盘子n进行分类讨论:

  • 1.当 n > m n \gt m n>m时,也就是盘子至少多一个,题目中不考虑顺序的影响,所以用不到的盘子不会影响最终结果,即 f ( m , n ) = f ( m , n − 1 ) f(m, n) = f(m, n - 1) f(m,n)=f(m,n1)
  • 2.当 n ≤ m 时 n \le m时 nm,也就是盘子够了,此时又可以进行两种分类讨论:
    • 2.1 至少有一个盘子为空:这种情况类似于情形1,即 f ( m , n ) = f ( m , n − 1 ) f(m, n) = f(m, n-1) f(m,n)=f(m,n1)
    • 2.2 全部盘子均不为空:每个盘子至少有一个苹果,那么所有盘子中的苹果都拿走一个,每个盘子的相对结果是相同的,即 f ( m , n ) = f ( m − n , n ) f(m,n) = f(m-n,n) f(m,n)=f(mn,n)
    • 上述两种分类讨论方法的分法为: f ( m , n ) = f ( m − n , n ) + f ( m , n − 1 ) f(m,n) = f(m-n, n) + f(m, n-1) f(m,n)=f(mn,n)+f(m,n1)

      综上所述:
      f ( m , n ) = { f ( m , n ) = f ( m , n − 1 ) if   n > m f ( m , n ) = f ( m − n , n ) + f ( m , n − 1 ) if   n ≤ m f(m,n) = \begin{dcases} f(m, n) = f(m, n - 1) &\text{if } ~ n > m \\ f(m,n) = f(m-n, n) + f(m, n-1) &\text{if } ~ n \le m \end{dcases} f(m,n)={f(m,n)=f(m,n1)f(m,n)=f(mn,n)+f(m,n1)if  n>mif  nm

可以看到,上述的等式,右边是左边减小规模的情况,典型的递归解法,那么递归便需要必要的三要素:结束条件、重复规律、减小规模

  1. 结束条件:如果只有一个盘子,即 n = 1 n=1 n=1时只有一种放法;如果没有苹果或只有一个苹果,也只有一种放法。所以, n = 1 n=1 n=1 或者 m = 1 m=1 m=1 时均是一种解法, r e t u r n   0 return ~ 0 return 0
  2. 重复规律:即上面分析的结果 f ( m , n ) = f ( m , n − 1 ) f(m, n) = f(m, n - 1) f(m,n)=f(m,n1)或者 f ( m , n ) = f ( m − n , n ) + f ( m , n − 1 ) f(m,n) = f(m-n, n) + f(m,n-1) f(m,n)=f(mn,n)+f(m,n1)
  3. 减小规模: f ( m , n ) = f ( m , n − 1 ) f(m, n) = f(m, n - 1) f(m,n)=f(m,n1)或者 f ( m , n ) = f ( m − n , n ) + f ( m , n − 1 ) f(m,n) = f(m-n, n) + f(m,n-1) f(m,n)=f(mn,n)+f(m,n1)中,每次调用对对m和n均进行规模的减小。

递归代码

"""
当m = 0或m = 1或n = 1,返回1
当n > m, f(m,n) = f(m,n-1)
当n <= m, f(m,n) = f(m-n, n) + f(m,n-1)
"""
def f(m: int, n: int):
    if m = 0 or m == 1 or n == 1:
        return 1
    elif n > m:
        return f(m, n - 1)
    else:
        return f(m-n, n) + f(m,n-1)


m_value, n_value = list(map(int, input().split(' ')))
print(f(m_value, n_value))

动态规划

动态规划如图所示,空了再写逻辑~~~
在这里插入图片描述

动态规划代码

先附上代码,分析后面再补~

def dp(m: int, n: int):
    arr = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    for i in range(1, n + 1):
        arr[0][i] = 1
        arr[1][i] = 1
    for j in range(m + 1):
        arr[j][1] = 1
    # 先行再列
    for row in range(2, m + 1):
        for col in range(2, n + 1):
            # 当n <= m, f(m,n) = f(m-n, n) + f(m,n-1)
            if row >= col:
                arr[row][col] = arr[row - col][col] + arr[row][col - 1]
            # 当n > m, f(m, n) = f(m, n - 1)
            else:
                arr[row][col] = arr[row][col - 1]
    return arr[m][n]

逻辑和递归有相似的地方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值