当前位置: 首页 > article >正文

代码随想录算法训练营第三十五天| 01背包问题 二维 、01背包问题 一维、416. 分割等和子集 。c++转java

背包理论基础

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

01背包问题 二维

题目我是在Acwing上面做的,思路可以参照上面理论基础说的01背包,题目如下:

AC代码如下:

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int v = scanner.nextInt();
        int[] value = new int[n];
        int[] weight = new int[n];
        for(int i = 0;i < n;i++){
            weight[i] = scanner.nextInt();
            value[i] = scanner.nextInt();
        }
        
        int[][] dp = new int[n][v + 1];
        
        for(int i = weight[0];i <= v;i++) dp[0][i] = value[0];
        for(int i = 1;i < n;i++){
            for(int j = 1;j <= v;j++){
                // 处理一下背包放不下的情况
                if(weight[i] > j ){
                    dp[i][j] = dp[i - 1][j];
                    continue;
                }
                dp[i][j] = Math.max(dp[i - 1][j],dp[i - 1][j - weight[i]] + value[i]);
                
            }
        }
        
        System.out.print(dp[n - 1][v]);
    }
}

01背包问题 一维

题目跟上面的是一样的,看题解:代码随想录

转成一维之后,我比较困惑的点就是为什么要倒着遍历...

因为怕dp[v]之后就不会更新了,那岂不是就找不到最大的了,

手动模拟一遍发现还是自己多虑了,逆着是为了不会重复取到一个物品,因为dp[j]已经保存了i - 1的最大值,所以只要考虑要不要加元素,后面的思路跟二维的这个是一样的。

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int v = scanner.nextInt();
        int[] value = new int[n];
        int[] weight = new int[n];
        for(int i = 0;i < n;i++){
            weight[i] = scanner.nextInt();
            value[i] = scanner.nextInt();
        }
        
        int[] dp = new int[v + 1];
        
        // for(int i = weight[0];i <= v;i++) dp[0][i] = value[0];
        for(int i = 0;i < n;i++){
            for(int j = v;j >= weight[i];j--){
                // 处理一下背包放不下的情况
                // if(weight[i] > j ){
                //     dp[i][j] = dp[i - 1][j];
                //     continue;
                // }
                dp[j] = Math.max(dp[j],dp[j - weight[i]] + value[i]);
                
            }
        }
        
        System.out.print(dp[v]);
    }
}

416. 分割等和子集

思路:先判断和是否为偶数,如果不是就返回false,剩下的部分用回溯做,只需要找到一组数等于sum/2就可以了,但是,超时了┭┮﹏┭┮,背包的确实没思路~,看题解:代码随想录

分析了一下,想不到用背包,主要是因为背包一般都是用来求最大值的,比如给定体积,求能装的价值最大,而这里是要判断是否可以找到一组数的和等于target。

但是这个问题也可以转换一下,就很🐂,转化的思路最关键的一点就是:对于容量为target的背包,我们要找这么一组数的和为target,其实也就是在求容量为target的包能装的最大价值,因为这里value = weight,所以dp[target]的最大值也就是target。

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 target = sum / 2;
        int[] dp = new int[target + 1];
        for(int i = 0;i < nums.length;i++){
            for(int j = target;j >= nums[i];j--){
                dp[j] = Math.max(dp[j],dp[j - nums[i]] + nums[i]);
            }
            if(dp[target] == target)
                return true;
        }
        return dp[target] == target;
    }
}


http://www.kler.cn/a/402293.html

相关文章:

  • C++创建型设计模式体现出的面向对象设计原则
  • unity3d————非实例化对象
  • 2024年中国AI大模型场景探索及产业应用调研报告:大模型“引爆”行业新一轮变革
  • Docker入门之Windows安装Docker初体验
  • Cargo Rust 的包管理器
  • rockylinux8.10默认分区方案
  • 鸿蒙实战:使用隐式Want启动Ability
  • 对数几率回归
  • 【phpseclib】 PHP 使用加密算法 RSA、DES、AES等
  • STM32低功耗设计NFC与无线距离感应智能钥匙扣-分享
  • 广东智能装备研发制造企业源代码防泄密|源代码防泄密解决方案
  • C++ | Leetcode C++题解之第565题数组嵌套
  • Argo workflow 拉取git 并使用pvc共享文件
  • Flutter:key的作用原理(LocalKey ,GlobalKey)
  • 二级等保要求及设备有哪些?
  • Go语言内存分配源码分析学习笔记
  • oracle导入线上数据的全步骤
  • 探究IOC容器刷新环节初始化前的预处理
  • 【电路笔记 通信】:数字式时分制指令响应型多路传输数据总线 1553协议 289A-97协议
  • Linux-第1集-基础指令 pwd、cd……入门