第九章 动态规划part03
正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。
如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。
如果做过背包类问题,可以先看视频,很多内容,是自己平时没有考虑到位的。
背包问题,力扣上没有原题,大家先了解理论,今天就安排一道具体题目。
详细布置
01背包问题 二维
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int bagweight = scanner.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
for (int i = 0; i < n; ++i) {
weight[i] = scanner.nextInt();
}
for (int j = 0; j < n; ++j) {
value[j] = scanner.nextInt();
}
int[][] dp = new int[n][bagweight + 1];
for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0];
}
for (int i = 1; i < n; i++) {
for (int j = 0; j <= bagweight; j++) {
if (j < weight[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
System.out.println(dp[n - 1][bagweight]);
}
}
视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6
01背包问题 一维
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取 M 和 N
int M = scanner.nextInt(); // 研究材料的数量
int N = scanner.nextInt(); // 行李空间的大小
int[] costs = new int[M]; // 每种材料的空间占用
int[] values = new int[M]; // 每种材料的价值
// 输入每种材料的空间占用
for (int i = 0; i < M; i++) {
costs[i] = scanner.nextInt();
}
// 输入每种材料的价值
for (int j = 0; j < M; j++) {
values[j] = scanner.nextInt();
}
// 创建一个动态规划数组 dp,初始值为 0
int[] dp = new int[N + 1];
// 外层循环遍历每个类型的研究材料
for (int i = 0; i < M; i++) {
// 内层循环从 N 空间逐渐减少到当前研究材料所占空间
for (int j = N; j >= costs[i]; j--) {
// 考虑当前研究材料选择和不选择的情况,选择最大值
dp[j] = Math.max(dp[j], dp[j - costs[i]] + values[i]);
}
}
// 输出 dp[N],即在给定 N 行李空间可以携带的研究材料的最大价值
System.out.println(dp[N]);
scanner.close();
}
}
视频讲解:https://www.bilibili.com/video/BV1BU4y177kY
416. 分割等和子集
本题是 01背包的应用类题目
class Solution {
public boolean canPartition(int[] nums) {
if(nums == null || nums.length == 0) return false;
int n = nums.length;
int sum = 0;
for(int num : nums) {
sum += num;
}
//总和为奇数,不能平分
if(sum % 2 != 0) return false;
int target = sum / 2;
int[] dp = new int[target + 1];
for(int i = 0; i < n; i++) {
for(int j = target; j >= nums[i]; j--) {
//物品 i 的重量是 nums[i],其价值也是 nums[i]
dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
}
//剪枝一下,每一次完成內層的for-loop,立即檢查是否dp[target] == target,優化時間複雜度(26ms -> 20ms)
if(dp[target] == target)
return true;
}
return dp[target] == target;
}
}
视频讲解:https://www.bilibili.com/video/BV1rt4y1N7jE