代码随想录算法训练营第35天|LeetCode 01背包问题 二维、01背包问题 一维、416. 分割等和子集

1. LeetCode 01背包问题 二维

题目链接:https://kamacoder.com/problempage.php?pid=1046
文章链接:https://programmercarl.com/背包理论基础01背包-1.html#算法公开课
视频链接:https://www.bilibili.com/video/BV1cg411g7Y6/

在这里插入图片描述

思路:
01背包问题

  1. 定义dp数组 dp[i][j]表示在0~i物品内任意选择,放入j空间大小的背包中的最大价值
    int[][] dp = new int[M][N+1];
  2. 递推公式
    dp[i][j] =
    Math.max(dp[i-1][j],dp[i-1][j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]))
  3. 初始化
    for (int j=Integer.valueOf(space[0]);j<=N;j++) {
    dp[0][j] = Integer.valueOf(value[0]);
    }
  4. 遍历顺序 先物品再空间

注意:
1️⃣若当前背包的容量都没有当前物品i大的时候,是不放物品i的。那么前i-1个物品能放下的最大价值就是当前情况的最大价值;
2️⃣若当前背包的容量可以放下物品i
那么此时分两种情况:
1、不放物品i
2、放物品i
比较这两种情况下,哪种背包中物品的最大价值最大

import java.util.*;

// 01背包问题
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] firLine = sc.nextLine().split(" ");
        String[] space = sc.nextLine().split(" ");
        String[] value = sc.nextLine().split(" ");
        int M = Integer.valueOf(firLine[0]); // 物品数量
        int N = Integer.valueOf(firLine[1]); // 背包空间
        
        // 1. 定义dp数组 dp[i][j]表示在0~i物品内选择j空间的最大价值
        int[][] dp = new int[M][N+1];
        
        // 2. 递推公式
        // dp[i][j] = Math.max(dp[i-1][j],
        // dp[i-1][j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]))
        
        // 3. 初始化
        for (int j=Integer.valueOf(space[0]);j<=N;j++) {
            dp[0][j] = Integer.valueOf(value[0]);
        }
    
        
        // 4. 遍历顺序 先物品再空间
        for (int i=1;i<M;i++) {
            for (int j=0;j<N+1;j++) {
                if (j < Integer.valueOf(space[i])) {
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = Math.max(dp[i-1][j],
                    dp[i-1][j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]));
                }
            }
        }
        
        System.out.println(dp[M-1][N]);
        
    }
}

2. LeetCode 01背包问题 一维

题目链接:https://kamacoder.com/problempage.php?pid=1046
文章链接:https://programmercarl.com/背包理论基础01背包-2.html#思路
视频链接:https://www.bilibili.com/video/BV1BU4y177kY/

思路:
01背包问题

  1. 确定dp数组的定义
    在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。
  2. 一维dp数组的递推公式
    dp[j]有两个选择:
    (1)不放物品i:取自己dp[j],相当于 二维dp数组中的dp[i-1][j];
    (2)放物品i:取dp[j - weight[i]] + value[i]。
    dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  3. 一维dp数组如何初始化
    关于初始化,一定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱。dp[0]应该是0,因为背包容量为0所背的物品的最大价值就是0。
    除了下标0的位置,假设物品价值都是大于0的,所以dp数组初始化的时候,都初始为0就可以了。
  4. 一维dp数组遍历顺序
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }// j>=weight[i],即物品i只能放到weight大于该物品重量的背包中。
}// 归根结底,当前物品只可能放入背包重量大于当前物品重量的背包中
import java.util.*;

// // 01背包问题
// // 二维数组
// public class Main {
//     public static void main(String[] args) {
//         Scanner sc = new Scanner(System.in);
//         String[] firLine = sc.nextLine().split(" ");
//         String[] space = sc.nextLine().split(" ");
//         String[] value = sc.nextLine().split(" ");
//         int M = Integer.valueOf(firLine[0]); // 物品数量
//         int N = Integer.valueOf(firLine[1]); // 背包空间
        
//         // 1. 定义dp数组 dp[i][j]表示在0~i物品内选择j空间的最大价值
//         int[][] dp = new int[M][N+1];
        
//         // 2. 递推公式
//         // dp[i][j] = Math.max(dp[i-1][j],
//         // dp[i-1][j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]))
        
//         // 3. 初始化
//         for (int j=Integer.valueOf(space[0]);j<=N;j++) {
//             dp[0][j] = Integer.valueOf(value[0]);
//         }
    
        
//         // 4. 遍历顺序 先物品再空间
//         for (int i=1;i<M;i++) {
//             for (int j=0;j<N+1;j++) {
//                 if (j < Integer.valueOf(space[i])) {
//                     dp[i][j] = dp[i-1][j];
//                 } else {
//                     dp[i][j] = Math.max(dp[i-1][j],
//                     dp[i-1][j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]));
//                 }
//             }
//         }
        
//         System.out.println(dp[M-1][N]);
        
//     }
// }

// 一维数组

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] firLine = sc.nextLine().split(" ");
        String[] space = sc.nextLine().split(" ");
        String[] value = sc.nextLine().split(" ");
        int M = Integer.valueOf(firLine[0]); // 物品数量
        int N = Integer.valueOf(firLine[1]); // 背包空间
        
        // 1. 定义dp数组 dp[j]表示空间j的背包的最大价值
        int[] dp = new int[N+1];
        
        // 2. 递推公式
        // dp[j] = Math.max(dp[j],dp[j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]))
        // 3. 初始化
    
        
        // 4. 遍历顺序 先物品再空间
        for (int i=0;i<M;i++) {
            for (int j=N;j>=Integer.valueOf(space[i]);j--) {
                dp[j] = Math.max(dp[j],dp[j-Integer.valueOf(space[i])]+Integer.valueOf(value[i]));
            }
        }
        
        System.out.println(dp[N]);
        
    }
}

3. LeetCode 416. 分割等和子集

题目链接:https://leetcode.cn/problems/partition-equal-subset-sum/description/
文章链接:https://programmercarl.com/0416.分割等和子集.html
视频链接:https://www.bilibili.com/video/BV1rt4y1N7jE/

在这里插入图片描述

思路:此题是01背包应用类题。
题目中物品是nums[i],重量是nums[i],价值也是nums[i],背包体积是sum/2。
只有确定了如下四点,才能把01背包问题套到本题上来。
1.背包的体积为sum / 2
2.背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
3.背包如果正好装满,说明找到了总和为 sum / 2 的子集。
4.背包中每一个元素是不可重复放入。

解法:
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 N = sum/2;

        //1. 定义dp数组 dp[j] 表示 容量j的背包所能获取的最大的物品价值
        // 注意:这里物品的重量=物品的价值。最大的物品价值=最大的物品重量
        int[] dp = new int[N+1];

        //2.递推公式
        //dp[j] = Math.max(dp[j],dp[j-nums[i]]+nums[i]);

        //3.初始化
        //4.遍历顺序 先物品再背包
        for (int i=0;i<nums.length;i++) {
            for (int j=N;j>=nums[i];j--) {
                dp[j] = Math.max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }

        return dp[N]==N;
    }
}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 06:26:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 06:26:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 06:26:03       45 阅读
  4. Python语言-面向对象

    2024-07-21 06:26:03       55 阅读

热门阅读

  1. Ollama

    2024-07-21 06:26:03       16 阅读
  2. OpenCV:使用cv2进行实时获取摄像头数据

    2024-07-21 06:26:03       16 阅读
  3. 洛谷U423720题解

    2024-07-21 06:26:03       12 阅读
  4. 【电子数据取证】如何配置好虚拟机

    2024-07-21 06:26:03       18 阅读
  5. Codeforces Round 959(Div. 1 + Div. 2)A~C

    2024-07-21 06:26:03       20 阅读
  6. linux 安装c语言编辑器

    2024-07-21 06:26:03       15 阅读
  7. pytorch学习(十三)torch维度变换

    2024-07-21 06:26:03       15 阅读
  8. Linux知识点汇总

    2024-07-21 06:26:03       18 阅读
  9. Leetcode 146. LRU 缓存

    2024-07-21 06:26:03       16 阅读
  10. 代码扫描常见问题盘点-并发处理类/异常类

    2024-07-21 06:26:03       17 阅读
  11. GESP C++ 二级真题(2023年12月)T1 小杨做题

    2024-07-21 06:26:03       12 阅读
  12. Python网络编程:socket模块的入门与实践

    2024-07-21 06:26:03       18 阅读
  13. Perl文件系统过滤:数据筛选的艺术

    2024-07-21 06:26:03       20 阅读