题目描述:
你正在安装一个广告牌,并希望它高度最大。这块广告牌将有两个钢制支架,两边各一个。每个钢支架的高度必须相等。
你有一堆可以焊接在一起的钢筋 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
sum(rods[i]) <= 5000
思路:
我们可以将这个问题转化为一个动态规划问题,使用两个状态来表示当前我们可以构成的高度差和某个支架的总高度。
设
dp[d]
表示两根支架的高度差为d
时,较矮的那根支架的最大可能高度。初始时dp[0] = 0
,表示高度差为 0 时,两根支架的高度都为 0。对于每个钢筋,我们有三个选择:
- 将钢筋放到第一根支架上,使得高度差增加;
- 将钢筋放到第二根支架上,使得高度差减少;
- 不使用该钢筋。
动态规划的状态转移方程可以如下定义:
- 如果我们将长度为
rod
的钢筋放到第一根支架上,则更新dp[d + rod] = max(dp[d + rod], dp[d])
;- 如果我们将钢筋放到第二根支架上,则更新
dp[d - rod] = max(dp[d - rod], dp[d] + rod)
;- 不使用该钢筋的情况则保持原样。
最后,返回
dp[0]
,即当两根支架高度相等时的最大高度。
代码实现:
from collections import defaultdict
class Solution:
def tallestBillboard(self, rods):
dp = defaultdict(int)
dp[0] = 0
for rod in rods:
current_dp = dp.copy()
for d in current_dp:
dp[d + rod] = max(dp[d + rod], current_dp[d])
dp[abs(d - rod)] = max(dp[abs(d - rod)], current_dp[d] + min(d, rod))
return dp[0]
# 测试
solution = Solution()
print(solution.tallestBillboard([1, 2, 3, 6])) # 输出应该是 6