1049. 最后一块石头的重量 II
题目
有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。
solution
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
weight_sum=sum(stones)
target=weight_sum//2
target2=weight_sum-target
#思路是:目标将所有的石头分成两堆(target1和target2)
#尽量把所有的石头分成sum和靠近target,剩余的就是另外一堆
#ans即为abs((sum-dp[target])-dp[target])
package=[0]*3000
dp=[]
for i in range(len(stones)):dp.append(package.copy())
for i in range(len(stones)):dp[i][0]=0
for j in range(len(package)):dp[0][j]+=stones[0]
for i in range(len(stones)):
for j in range(target+1):
if j>=stones[i]:
dp[i][j]=max(dp[i-1][j-stones[i]]+stones[i],dp[i-1][j])
else:
dp[i][j]=dp[i-1][j]
return abs((weight_sum-dp[len(stones)-1][target])-dp[len(stones)-1][target])
494 target sum
backpack method (ac)
import numpy as np
# use backtracking do it again
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
sum_array=sum(nums)
if abs(target)>sum_array:return 0
if (sum_array-target)%2!=0:return 0
else:
pos=(sum_array+target)//2
neg=(sum_array-target)//2
capacity=min(pos,neg)
dp=np.zeros((len(nums)+1,capacity+1))
# initialize
# initialize
# we add one more row to indicate that dp[i][j] means we use the first i items in the array and the initial dp[0][0] means we don't have item to put in to the bag -> no action.
dp[0][0]=1
for i in range(1,len(dp)):
for j in range(len(dp[0])):
if j>=nums[i-1]:
dp[i][j]=int(dp[i-1][j]+dp[i-1][j-nums[i-1]])
else:
dp[i][j]=dp[i-1][j]
print(dp)
return int(dp[-1][-1])
backtracking method (need try)
474. Ones and Zeroes
本质是是:01背包问题的多维背包版本
以下二维数组并不是表示是01背包的二维数组解法,而是一维滚动数组的二维背包版
from collections import Counter
import numpy as np
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
strs_dict=dict()
for i in range(len(strs)):
strs_dict[i]=Counter(strs[i])
print(strs_dict)
dp=np.zeros((m+1,n+1))
# dp[i][j] means
for k in range(len(strs)):
if '0' in strs_dict[k]: zeronum=strs_dict[k]['0']
else:zeronum=0
if '1' in strs_dict[k]:onenum=strs_dict[k]['1']
else:onenum=0
for i in range(m,zeronum-1,-1): # zeronum<=i<=m
for j in range(n,onenum-1,-1):
dp[i][j]=max(dp[i][j],dp[i-zeronum][j-onenum]+1)
# print(dp)
return int(dp[m][n])
01背包问题总结
二维数组:dp[i][j]表示使用前i个物品,装容量为j的背包的最大价值
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight(i)]+value(i))
先遍历物品,再遍历背包,反之亦可。
遍历背包的顺序可以正序也可以倒序
一维数组:dp[j]表示装容量为j的背包的最大价值
dp[j]=max(dp[j],dp[j-weight(i)]+value(i))
for k in range(len(strs)): # 遍历物品
for i in range(m,zeronum-1,-1): # 遍历背包 倒序
for j in range(n,onenum-1,-1):