题目
你正在安装一个广告牌,并希望它高度最大。这块广告牌将有两个钢制支架,两边各一个。每个钢支架的高度必须相等。
你有一堆可以焊接在一起的钢筋 rods。举个例子,如果钢筋的长度为 1、2 和 3,则可以将它们焊接在一起形成长度为 6 的支架。
返回广告牌的最大可能安装高度。如果没法安装广告牌,请返回 0。
示例 1:
输入:[1,2,3,6]
输出:6
解释:我们有两个不相交的子集 {1,2,3} 和 {6},它们具有相同的和 sum = 6。
示例 2:
输入:[1,2,3,4,5,6]
输出:10
解释:我们有两个不相交的子集 {2,3,5} 和 {4,6},它们具有相同的和 sum = 10。
示例 3:
输入:[1,2]
输出:0
解释:没法安装广告牌,所以返回 0。
提示:
0 <= rods.length <= 20
1 <= rods[i] <= 1000
钢筋的长度总和最多为 5000
思路
最大的总和为5000, 设第一条支架长度a, 第二条长b, 可以归约为带约束条件a == b
的a最大化和问题, 如果以a + b作为状态表示, 状态只会单调变化(a + b单调增大), 如果用a - b表示状态, 如果以map结构存储数据可以明确知道返回的结果下标: 0, 此时正好满足约束条件a == b
.
设map键是v = a - b, 值是a的最大值, 可以写出动规递推式, rod为当前取出的钢筋的长度, 如果加到第一条支架上是 v + rod, 加到第二条支架上是 v - rod, 值保存第一条支架的最大长度, 所以如果加到第一条支架上就更新为max(dp[v + rod], a + rod)
, 如果加到第二条支架更新为max(dp[v - rod], a)
, 遍历一遍整个钢筋数组, 每条钢筋加到a/b上或者丢弃, 按递推式计算一遍就得到满足约束条件时a的最大值dp[0].
dp[v + rod] = max(dp[v + rod], a + rod);
dp[v - rod] = max(dp[v - rod], a);
代码
class Solution {
public:
int tallestBillboard(vector<int>& rods) {
unordered_map<int, int> dp;
dp[0] = 0;
for(auto rod: rods){
unordered_map<int, int> dp2(dp);
for(auto each: dp2){
int v{each.first}, a{each.second};
dp[v + rod] = max(dp[v + rod], a + rod);
dp[v - rod] = max(dp[v - rod], a);
}
}
return dp[0];
}
};