01背包的理论基础可以参考一下这个,真心觉得不错错
看完上边这个之后,应该对背包问题有了一个初步的了解了,那接下来趁热打铁,看看下边这个
01背包的简化,之后的题主要靠这个
==============================================================================
第一题:力扣416题
解题思路:
可以把数组之和的一半作为背包所能承受的最大重量,把数组中的每个数当作是要往书包中投放的物品,然后就先遍历每个物品,紧接着倒叙遍历背包。主要的还是递推公式:无非就是两种情况,第一种,该物品的重量大于此时背包所能承受的重量,不放它的收益;另一种就是放上这个物品,看看此时收益,二者取最大的即可。
代码如下:
class Solution {
public boolean canPartition(int[] nums) {
//先求和,用来作为分子集的标准
int sum = 0;
for(int num : nums) {
sum += num;
}
//求完和之后判断一下,能不能劈两半
if(sum % 2 == 1) {
return false;
}
//开始转换成 01背包问题 了
int target = sum / 2;
//因为还得放0
int[] dp = new int[target+1];
//先遍历物品,在遍历背包,并且背包得反向遍历
for(int i = 0; i < nums.length; i++) {
for(int j = target; j >= nums[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
}
}
return target == dp[target];
}
}
类似题目:力扣1049题
直接放代码:
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for(int stone : stones) {
sum += stone;
}
int target = sum / 2;
int[] dp = new int[target+1];
for(int i = 0; i < stones.length; i++) {
for(int j = target; j >= stones[i]; j--) {
dp[j] = Math.max(dp[j], dp[j-stones[i]] + stones[i]);
}
}
return sum - 2 * dp[target];
}
}
就是最后的处理方式不同
==============================================================================
第二题:力扣494题
代码如下:
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
if ((target + sum) % 2 != 0) {
return 0;
}
if(Math.abs(target) > sum) {
return 0;
}
int size = (target + sum) / 2;
int[] dp = new int[size + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = size; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[size];
}
}
可以做下这个题:力扣474题