【蓝桥杯真题】动态规划之数的划分

数的划分🍉

将正数n分为k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

例如:n=7,k=3,下面三种分法被认为是相同的。

1, 1, 5;

1, 5, 1;

5, 1, 1.

问有多少种不同的分法。

输入描述

输入一行。2个正数n, k,且 6\leq n\leq 200, 2\leq k \leq 6

输出描述

输出一个正数,即不同的分法。

输入样例

7 3

输出样例

4

思路题解

这一题实际上是组合数学里面的经典问题:将i个小球放到j个盒子中,小球之间与盒子之间没有区别,并且最后的结果不允许空盒。我们首先定义一个二维数组dp[][],dp[i][j]表示将整数 i 划分为 j 份 的方案数。dp[i][j]的动态转移方程为 :

该如何理解这个式子呢?我们重点看这一句话:不允许空盒

我们使用题目的输入案例作为一个具体的例子来解释:i=7,j=3,因此现在我们有3个盒子,我们必须先拿出 3个盒子,将 3个盒子分别放上一个小球,保证每个盒子不空,即现在每个盒子的值为1,那么现在i=7变成了i-j=4,即i=4,这不难理解:一共7个小球,代表着7个1,现在将其中3个小球放进三个盒子,所以只剩下了4个小球,变成了dp[4][3],即dp[i-j][j]问题。

那么接下来我们又该如何处理呢?我们可以将剩下的所有小球都放到一个盒子里面去(dp[i-j][1]),也可以分到两份中去(dp[i-j][2]) ,...,也可以分到j份中(dp[i-j][j]),而每一种分发都是不相同的,所以可以将每一种分法全部加起来,和即为dp[i][j]。

想必看到这里,大家都懂得了这个算法啦!不过这个式子还可以变得更加优美一点儿:求dp[i-1][j-1],具体优化方法如下:

从而最终的式子为: 

AC code

n, k = map(int, input().split())

# 初始化一个二维数组,用于存储 f(n, m)
dp = [[0 for j in range(210)] for i in range(210)]
for i in range(1, n+1):
   dp[i][1] = 1
   dp[i][i] = 1
'''
(7 3)->(4 3)+(6 2)
'''
for i in range(3, n+1):
   for j in range(2, k+1):
       if i > j:
           dp[i][j] = dp[i-j][j] + dp[i-1][j-1]

print(dp[n][k])
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大气层煮月亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值