1049. 最后一块石头的重量 II
与前一道分割等和子集的思路差不多,都是01背包问题。因为是采用滚动数组的形式,所以必须要倒序遍历才可以。
dp[i]代表着在i的限制下最大的承重。所以另一半就是all - dp【all / 2】
func lastStoneWeightII(stones []int) int {
all := 0
for i := 0; i < len(stones); i++{
all += stones[i]
}
sum := all/ 2
dp := make([]int, sum + 1)
for i := 0; i < len(stones);i++{
for j := sum; j>= stones[i];j--{
dp[j] = int(math.Max(float64(dp[j]), float64(dp[j - stones[i]] + stones[i])))
}
}
return all - 2 * dp[sum]
}
494. 目标和
注意点比较多:
1、这是求次数的,所以是dp【j】 += dp【j - nums【i】】
2、要注意什么时候是不可能完成的
3、dp初值要赋好,dp【0】 = 1(但是对于普通的01背包的dp数组初始化为0就可以。)
func findTargetSumWays(nums []int, target int) int {
sum := 0
for i := 0; i < len(nums); i++{
sum += nums[i]
}
if int(math.Abs(float64(target))) > sum {return 0} // 此时没有方案
if (sum + target) % 2 == 1 {return 0}// 此时没有方案
pos := (sum + target) / 2
dp := make([]int, pos + 1)
dp[0] = 1
for i := 0; i < len(nums); i++{
for j := pos; j >= nums[i]; j--{
dp[j] += dp[j - nums[i]]
}
}
return dp[pos]
}
474.一和零
看似是一个多重背包的问题,但是实际上是一个01背包,只是限制条件增加了,变成了一个两个维度的背包。
func findMaxForm(strs []string, m int, n int) int {
dp := make([][]int, m + 1)
for i := 0 ; i <= m; i++{
dp[i] = make([]int, n + 1)
}
for i := 0; i < len(strs); i++{
zero := 0
one := 0
for j := 0; j < len(strs[i]); j++{
if strs[i][j] == '0'{
zero++
}else{
one++
}
}
for j := m; j >= zero; j--{
for k := n; k >= one; k--{
dp[j][k] = int(math.Max(float64(dp[j][k]) , float64(dp[j - zero][k - one] + 1)))
}
}
}
return dp[m][n]
}