【代码随想录Day34】动态规划Part03

0-1 背包问题 二维

题目链接/文章讲解:代码随想录

视频讲解:带你学透 0-1 背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili

java 复制代码
import java.util.Scanner;

public class Main1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 物品数量
        int bagweight = sc.nextInt(); // 背包容量

        int[] weight = new int[n];
        int[] value = new int[n];

        // 输入物品的重量
        for (int i = 0; i < n; i++) {
            weight[i] = sc.nextInt();
        }

        // 输入物品的价值
        for (int i = 0; i < n; i++) {
            value[i] = sc.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]);
    }
}

0-1 背包问题 一维

题目链接/文章讲解:代码随想录

视频讲解:带你学透 01 背包问题(滚动数组篇) | 从此对背包问题不再迷茫!_哔哩哔哩_bilibili

java 复制代码
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 物品数量
        int bagweight = sc.nextInt(); // 背包容量

        int[] weight = new int[n];
        int[] value = new int[n];

        // 输入物品的重量
        for (int i = 0; i < n; i++) {
            weight[i] = sc.nextInt();
        }

        // 输入物品的价值
        for (int i = 0; i < n; i++) {
            value[i] = sc.nextInt();
        }

        // 使用一维数组进行动态规划
        int[] dp = new int[bagweight + 1];

        // 填充动态规划数组
        for (int i = 0; i < n; i++) {
            for (int j = bagweight; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }

        // 输出结果
        System.out.println(dp[bagweight]);
    }
}

416. 分割等和子集

题目链接/文章讲解:代码随想录

视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibili

java 复制代码
class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }

        // 如果总和是奇数,无法分成两个相等的子集
        if (sum % 2 != 0) {
            return false;
        }

        int target = sum / 2;
        int n = nums.length;

        // 创建一个 dp 数组,表示是否可以达到特定的和
        boolean[][] dp = new boolean[n + 1][target + 1];

        // 初始化:可以达到和为 0
        for (int i = 0; i <= n; i++) {
            dp[i][0] = true;
        }

        // 填充 dp 数组
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= target; j++) {
                if (j < nums[i - 1]) {
                    // 当前数字大于目标和,无法选择它
                    dp[i][j] = dp[i - 1][j];
                } else {
                    // 选择当前数字或不选择它
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
                }
            }
        }

        // 返回能否达到 target
        return dp[n][target];
    }
}

代码解释

  1. 计算总和 : 首先通过一个循环计算 nums 数组的总和 sum

  2. 检查奇偶性 : 如果 sum 是奇数,则不可能将数组分成两个相等的子集,直接返回 false

  3. 动态规划数组 : 创建一个二维布尔数组 dp,其中 dp[i][j] 表示前 i 个数字是否可以组成和为 j 的子集。

  4. 初始化:

    • 任何情况下,和为 0 只需要不选择任何数字,因此 dp[i][0] 都是 true
  5. 填充 dp 数组:

    • 通过两层循环遍历每个数字和每个可能的和。如果当前数字大于目标和 j,则无法选择它,dp[i][j] 等于不选择它的结果 dp[i-1][j]
    • 如果可以选择当前数字,则 dp[i][j] 等于选择当前数字或不选择它的结果,即 dp[i][j] = dp[i-1][j] || dp[i-1][j - nums[i - 1]]
  6. 返回结果 : 最后返回 dp[n][target],表示是否可以用前 n 个数字组成和为 target 的子集。

相关推荐
Cx330❀2 分钟前
【数据结构初阶】--单链表(二)
数据结构·经验分享·算法·leetcode
计算机毕设定制辅导-无忧学长15 分钟前
InfluxDB 集群部署与高可用方案(二)
java·linux·前端
SimonKing15 分钟前
Mysql分页:高效处理海量数据的核心技术
java·后端·程序员
chy存钱罐19 分钟前
模型拟合问题全解析:从欠拟合、过拟合到正则化(岭回归与拉索回归)
人工智能·算法·机器学习·数据挖掘·回归
weisian15120 分钟前
力扣经典算法篇-45-回文数(数字处理:求余+整除,字符串处理:左右指针)
算法·leetcode·职场和发展
C灿灿数模22 分钟前
2025国赛数学建模C题详细思路模型代码获取,备战国赛算法解析——决策树
c语言·算法·数学建模
寻星探路28 分钟前
常用排序方法
java·开发语言·算法
2301_8098152530 分钟前
C语言与数据结构:从基础到实战
数据结构
青云交31 分钟前
Java 大视界 -- 基于 Java 的大数据实时流处理在工业物联网设备故障预测与智能运维中的应用(384)
java·大数据·物联网·flink·设备故障预测·智能运维·实时流处理
半桔41 分钟前
【STL源码剖析】从源码看 vector:底层扩容逻辑与内存复用机制
java·开发语言·c++·容器·stl