n = 2022 m = 10 # dp[i][j][k] 从1到i之间取j个数和为k的方案数 dp = [[[0] * (n + 1) for i inrange(m + 1)] for j inrange(n + 1)]
# 初始状态:从前i个数中取0个数和为0,方案数是1 for i inrange(0, n + 1): dp[i][0][0] = 1
for i inrange(1, n + 1): for j inrange(1, m + 1): for k inrange(1, n + 1): if i > k: dp[i][j][k] = dp[i - 1][j][k] else: dp[i][j][k] = dp[i - 1][j - 1][k - i] + dp[i - 1][j][k] print(dp[n][m][n])
将题目转为0/1背包问题:
容量2022的包,编号1到2022的物体大小就是编号,取10个使得刚好装满的方案数。
我不好理解的是初始状态的设定。
滚动数组的做法:
1 2 3 4 5 6 7 8 9 10 11 12 13
n = 2022 m = 10 # dp[i][j][k] 从1到i之间取j个数和为k的方案数 dp = [[0] * (n + 1) for i inrange(m + 1)]
# 初始状态:从取0个数和为0,方案数是1 dp[0][0] = 1
for i inrange(1, n + 1): for j inrange(m, 0, -1): for k inrange(i, n + 1): dp[j][k] += dp[j - 1][k - i] print(dp[m][n])