最高的广告牌:找两个相同子集的最大和,砝码问题
你正在安装一个广告牌,并希望它高度最大。这块广告牌将有两个钢制支架,两边各一个。每个钢支架的高度必须相等。你有一堆可以焊接在一起的钢筋 rods。举个例子,如果钢筋的长度为 1、2 和 3,则可以将它们焊接在一起形成长度为 6 的支架。返回广告牌的最大可能安装高度。如果没法安装广告牌,请返回 0。
solution
- 可以将问题简化为:给每个元素加上(0,-1,1)的系数,使得和为0,令系数为1的元素之和最大。
- 解决思路:维护一个DP[key]: 表示 两根柱子差为 key 时的最长公共长度。这里为了减少内存,使用字典来进行保存。
- 初始状态:当key=d时,如下图,此时的DP[key]=DP[d]=len(red):
- 若此时来了一个新的柱子长度为 x,x被加在了长的那一根柱子上:
D
P
[
k
e
y
+
x
]
=
m
a
x
(
D
P
[
k
e
y
]
,
D
P
[
k
e
y
+
x
]
)
DP[key+x] = max(DP[key],DP[key+x])
DP[key+x]=max(DP[key],DP[key+x]) , 相当于说 红色的长度没有变
- 若此时来了一个新的柱子长度为 x,x被加在了短的那一根柱子上:
D
P
[
a
b
s
(
k
e
y
−
x
)
]
=
m
a
x
(
m
e
m
.
g
e
t
(
a
b
s
(
k
e
y
−
x
)
,
0
)
,
D
P
[
k
e
y
]
+
m
i
n
(
k
e
y
,
x
)
)
DP[abs(key-x)]=max(mem.get(abs(key-x),0),DP[key]+min(key,x))
DP[abs(key−x)]=max(mem.get(abs(key−x),0),DP[key]+min(key,x)) 取abs是因为存在
d
>
x
d>x
d>x 和
d
<
x
d<x
d<x 的情况:
- 若此时来了一个新的柱子长度为 x,x被加在了长的那一根柱子上:
D
P
[
k
e
y
+
x
]
=
m
a
x
(
D
P
[
k
e
y
]
,
D
P
[
k
e
y
+
x
]
)
DP[key+x] = max(DP[key],DP[key+x])
DP[key+x]=max(DP[key],DP[key+x]) , 相当于说 红色的长度没有变
class Solution(object):
def tallestBillboard(self, rods):
"""
:type rods: List[int]
:rtype: int
"""
#DP[key]:表示差为key的最大公共长度
mem={0:0}
for x in rods:
cur = mem.copy()
for key,val in cur.items():
##mem.get(key+x,0)):从 mem 中取 (key+x) 如果有这个key就取,没有则返回0
mem[key+x] = max(mem.get(key+x,0),val)
mem[abs(key-x)]=max(mem.get(abs(key-x),0),val+min(key,x))
# print(mem)
return mem[0]