背包问题之0-1背包
0-1背包是最基本的背包问题,其核心思路就在于每个物品的放与不放(每个物品最多只能放一次)
一个最简单经典的0-1背包例题
题目
有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.
问最多能装入背包的总价值是多大?
样例
输入: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
输出: 9
解释: 装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9
解题代码
public int backPackII(int m, int[] A, int[] V) {
int[] dp = new int[m + 1];
for(int i = 0;i < A.length;i++){//外层物品
for(int j = m;j >= A[i];j--){//内层背包容量
dp[j] = Math.max(dp[j - A[i]] + V[i],dp[j]);//当亲物品循环的每一个结果由上一个物品的循环结果转移而来,从而保证每个物品只使用一次。
}
}
return dp[m];
}
再来一个例子
此例主要是为了体会不同的问题运用0-1背包思路解题时需要思考具体在dp数组中存什么?相应的状态转移方程怎么写。
题目
给出 n 个物品, 以及一个数组, nums[i] 代表第i个物品的大小, 保证大小均为正数, 正整数 target 表示背包的大小, 找到能填满背包的方案数。
每一个物品只能使用一次
解题代码
public int backPackV(int[] nums, int target) {
int[] dp = new int[target + 1];
int count = 0;
dp[0] = 1;
for(int i = 0;i < nums.length;i++){
for(int j = target;j >= nums[i];j--){
dp[j] = dp[j - nums[i]] + dp[j];//dp中存的是能够填满容量为i的背包的方案数
}
}
return dp[target];
}