题目:有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。
分析:根据LC494的思想,做如下分析
① 由题目可知: pos + neg = sum 求 pos - neg 最小 即 sum-2neg 最小 sum-2neg>=0 neg<=sum/2 当取 = 时,有最小值。(即neg要在不超过sum/2的情况下尽可能的大)
② 转化为背包问题:
物品容量:stones(n=len(stones)) 背包容量:bag=sum/2 价值:stones
状态:d[i][j] 当 背包容量为 j 时,第0-i个物品的最大价值
状态转移方程:d[i][j] = max(不放当前物品的价值,当前物品价值+背包剩余空间产生的价值)
= max(d[i-1][j], stones[i-1]+d[i-1][j-stones[i-1]])
初始状态: 背包[0-bag] 物品[0-n]
d[0][:]=0 当物品为空时候 无论背包多大 价值为0
d[:][0]=0 当背包容量为0时候,什么都放不下,价值为0
PS:①当感觉像0-1背包问题,就要对应各个已知往上边靠。
②注意最后返回的是 sum(stones) - d[-1][-1]*2
代码:
def lastStoneWeightII2(stones):
n, bag = len(stones), sum(stones)//2
d = [[0 for _ in range(bag+1)] for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, bag+1):
if j >= stones[i-1]:
d[i][j] = max(d[i-1][j], stones[i-1] + d[i-1][j-stones[i-1]])
else:
d[i][j] = d[i-1][j]
return sum(stones) - d[-1][-1]*2
368

被折叠的 条评论
为什么被折叠?



