01背包问题 二维
视频讲解:带你学透0-1背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili
dp[i][j]数组含义:从0-i物品中任取,放入容量为j的背包中时,最大的价值
递推公式:dp[i][j] = Math.max(dp[i - 1][j] , dp[i - 1][j - space[i]] + value[i]); 放i和不放i哪个价值最大
if(space[i] > j) dp[i][j] = dp[i - 1][j]; //如果i的体积比j大,不能放i
import java.util.*;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[] space = new int[m];
int[] value = new int[m];
for(int i = 0;i < m;i++){
space[i] = sc.nextInt();
}
for(int i = 0;i < m;i++){
value[i] = sc.nextInt();
}
int[][] dp = new int[m][n + 1];
//初始化行
for(int i = 1;i < n + 1;i++){
if(space[0] <= i)dp[0][i] = value[0];
}
//初始化列
for(int i = 0;i < m;i++){
dp[i][0] = 0;
}
for(int i = 1;i < m;i++){
for(int j = 1;j < n + 1;j++){
if(space[i] > j){//如果i的体积比j大,不能放i
dp[i][j] = dp[i - 1][j];
}else{
dp[i][j] = Math.max(dp[i - 1][j],
dp[i - 1][j - space[i]] + value[i]);
}
}
}
System.out.println(dp[m - 1][n]);
}
}
01背包问题 一维
视频讲解:带你学透01背包问题(滚动数组篇) | 从此对背包问题不再迷茫!_哔哩哔哩_bilibili
import java.util.*;
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]);
}
}
System.out.println(dp[N]);
scanner.close();
}
}
416. 分割等和子集
本题是 01背包的应用类题目
视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibili
nums[i]既是空间又是价值
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for(int i = 0;i < nums.length;i++){
sum += nums[i];
}
if(sum % 2 == 1)return false;//总和为奇数时不能分割
int[] dp = new int[sum / 2 + 1];
Arrays.fill(dp,0);
for(int i = 0;i < nums.length;i++){
for(int j = sum/2;j >= nums[i];j--){
dp[j] = Math.max(dp[j],dp[j - nums[i]] + nums[i]);
if(dp[sum/2] == sum/2)return true;//剪枝,发现可以装到sum/2就可以了
}
}
if(dp[sum / 2] == sum / 2)return true;
else return false;
}
}

被折叠的 条评论
为什么被折叠?



