【动态规划】绝对能看懂的题解,数的划分

题目

【动态规划】绝对能看懂的题解,数的划分_第1张图片

思路题解

这一题实际上是组合数学里面的经典问题:将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],具体优化方法如下:

从而最终的式子为: 

代码实现

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])

你可能感兴趣的:(#,阿良的Python算法,动态规划,算法)