我一直在研究这个问题。
- 目标是使用砖块建造楼梯
- 有N个砖块,必须全部用于建造楼梯
- 楼梯由严格递增的不同大小的阶梯组成
- 不允许楼梯有相同大小的阶梯
- 每个楼梯至少有两个阶梯,并且每个阶梯都包含至少一个砖块
完整问题链接 http://acm.timus.ru/problem.aspx?num=1017&locale=en
我已经知道这个问题涉及到不同分区和数论/背包问题。目标是给定列表n = [1,2,3,....n -1],确定存在多少个无序集合加起来等于N。我说无序是因为给定列表没有重复项,所以任何组合可以排序为符合规则的特定回答。我也理解一般的概念是从高度1开始,并添加所有可能的组合,直到新高度用完所有剩余的砖块为止。我意识到有一些模式,比如你已经知道n = 3时存在多少分区,当进入4时,因此使用该数据(动态规划)是解决方案的一部分。
最终我找到了以下解决方案。
n = int(input())
m = [[0 for i in range(n + 1)] for j in range(n + 1)]
m[0][0] = 1 # base case
for last in range(1, n + 1):
for left in range(0, n + 1):
m[last][left] = m[last - 1][left]
if left >= last:
m[last][left] += m[last - 1][left - last]
print(m[n][n] - 1)
因此,我理解最后一个变量表示使用多少个砖头。左循环使其在所有可能的楼梯中运行并传输缓存数据。因此,我理解m [last] [left]被分配给上面的条目,因为它已经计算了使用last-1块砖制作所有可能的楼梯的分区总和。
我还知道对角线保存所有分区计数([3,3] =不同的砖块分区= 3)。我不确定的部分是对角线检查之后数据如何确定(如果left> = last),算法如何知道将该精确矩阵位置添加到当前索引会得到正确的值?这些点处的数据之间的关系是什么?
下面是在10上运行后的2d数组的矩阵,答案为9
= 0 1 2 3 4 5 6 7 8 9 10
0 |1 0 0 0 0 0 0 0 0 0 0
1 |1 1 0 0 0 0 0 0 0 0 0
2 |1 1 1 1 0 0 0 0 0 0 0
3 |1 1 1 2 1 1 1 0 0 0 0
4 |1 1 1 2 2 2 2 2 1 1 1
5 |1 1 1 2 2 3 3 3 3 3 3
6 |1 1 1 2 2 3 4 4 4 5 5
7 |1 1 1 2 2 3 4 5 5 6 7
8 |1 1 1 2 2 3 4 5 6 7 8
9 |1 1 1 2 2 3 4 5 6 8 9
10 |1 1 1 2 2 3 4 5 6 8 10