题目描述
你正在安装一个广告牌,并希望它高度最大。这块广告牌将有两个钢制支架,两边各一个。每个钢支架的高度必须相等。
你有一堆可以焊接在一起的钢筋。举个例子,如果钢筋的长度为 1、2 和 3,则可以将它们焊接在一起形成长度为 6 的支架。
返回广告牌的最大可能安装高度。如果没法安装广告牌,请返回 0。
样例
输入:[1,2,3,6]
输出:6
解释:我们有两个不相交的子集 {1,2,3} 和 {6},它们具有相同的和 sum = 6。
输入:[1,2,3,4,5,6]
输出:10
解释:我们有两个不相交的子集 {2,3,5} 和 {4,6},它们具有相同的和 sum = 10。
输入:[1,2]
输出:0
解释:没法安装广告牌,所以返回 0。
注意
0 <= rods.length <= 20
1 <= rods[i] <= 1000
钢筋的最大长度最多为 5000
算法
(动态规划) $O(n \cdot \sum {rods[i]})$
- 状态 $f(i, j)$ 表示考虑了前 $i$ 个钢筋,搭建的两个钢制支架差距为 $j$ 时,较低的支架的最大高度是多少。
- 初始化 $f(i, j) = -\infty$,$f(0, 0) = 0$。
- 转移时,如果不用第 $i$ 个钢筋,则 $f(i, j) = \max (f(i, j), f(i - 1, j))$;如果使用了第 $i$ 个钢筋,设它的高度为
x
,并将它放到了较高的支架上,则差距会扩大x
,即 $f(i, j + x) = \max (f(i, j + x), f(i - 1, j))$;若放到了较低的支架上,并且x
小于等于差距 $j$,则 $f(i, j - x) = \max (f(i, j - x), f(i - 1, j) + x)$,否则 $f(i, x - j) = \max (f(i, x - j), f(i - 1, j) + j)$。 - 最终答案为 $f(n, 0)$。
时间复杂度
- 总共 $n \cdot \sum {rods[i]}$ 个状态,每个状态有四种转移,故总时间复杂度为 $O(n \cdot \sum {rods[i]})$。
C++ 代码
class Solution {
public:
int tallestBillboard(vector<int>& rods) {
int n = rods.size(), sum = 0;
vector<vector<int>> f(n + 1, vector<int>(5010, -5010));
f[0][0] = 0;
for (int i = 1; i <= n; i++) {
sum += rods[i - 1];
for (int j = 0; j <= sum; j++) {
f[i][j] = max(f[i][j], f[i - 1][j]);
int x = rods[i - 1];
if (j + x <= sum)
f[i][j + x] = max(f[i][j + x], f[i - 1][j]);
if (x <= j)
f[i][j - x] = max(f[i][j - x], f[i - 1][j] + x);
else
f[i][x - j] = max(f[i][x - j], f[i - 1][j] + j);
}
}
return f[n][0];
}
};
2021.3.24 华为笔试第二题打卡
不过题解里这句话:若放到了较低的支架上,并且差距 j小于等于 rods[i]
是不是应该改为j大于等于rods[i]
已修正
赞👍