代码随想录算法训练营第四十四天 _ 动态规划_完全背包问题、518.零钱兑换II、377.组合总和IV。

news2024/11/28 20:54:51

学习目标:

动态规划五部曲:
① 确定dp[i]的含义
② 求递推公式
③ dp数组如何初始化
④ 确定遍历顺序
⑤ 打印递归数组 ---- 调试
引用自代码随想录!

60天训练营打卡计划!

学习内容:

完全背包问题 – 二维dp数组

  • 动态规划五步曲:
    ① 确定dp[i][j]的含义 : 任取[0, i]的物品(可重复使用)后放进容量为j的背包 所能放的 最大价值
    ② 求递推公式 : dp[i][j] = Math.max(dp[i-1][j], dp[i][j-weight[i]] + value[i]);
    Ⅰ 不放物品 i : dp[i][j] = dp[i-1][j];
    Ⅱ 放物品 i : dp[i][j-weight[i]] + value[i] 依赖本行已填充的值
    ③ dp数组如何初始化 : 对第一行进行单独的初始化,如下图所示。当背包容量大于第一个物品的重量时开始放入背包,一直连续放入。
    ④ 遍历顺序:先遍历物品,再遍历背包,和01背包问题一致。

下面的代码应该是没问题的,但是数字量变大之后会很容易超时。在这里插入图片描述

// 动态规划
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //m,n分别代表物品种类和背包容量
        int itemSize = 0,bagSize = 0;
        Scanner sc = new Scanner(System.in);
        //获取itemSize和bagSize的值
        itemSize = sc.nextInt();
        bagSize = sc.nextInt();
        //初始化对应的重量数组和价值数组
        int[] weight = new int[itemSize];
        int[] value = new int[itemSize];
        //这两个都是物品的属性,大小只和物品数量有关
        for(int i = 0;i < itemSize;i++){
            weight[i] = sc.nextInt();
            value[i] = sc.nextInt();
        }
        
        // 完全背包问题
        testWeightBagProblem(weight,value,bagSize);
    }

    /**
     * 动态规划获得结果
     * @param weight  物品的重量
     * @param value   物品的价值
     * @param bagSize 背包的容量
     */
    public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){

        int itemSize = weight.length;
        // dp数组的含义是:在[0,i]件物品中选择是否放入背包 的 最大价值
        int[][] dp = new int[itemSize][bagSize+1];
        
        int val = 0;
        
        // 初始化dp数组,默认都为0.
        // 使用最小重量的物品为该物品所在行赋值
        for(int j = weight[0]; j < bagSize+1; j++){
            if(j % weight[0] == 0)  val += value[0];
            dp[0][j] = val;
        }
        
        // 正常的为dp数组赋值,依赖左上位置的其他的dp值
        for(int i = 1; i < itemSize; i++){
            // j是背包容量
            for(int j = 1; j < bagSize+1; j++){
                // 如果容量可以放入新的物品,则从本行的左侧继承
                if(j >= weight[i]){
                    // 一定要填j < weight[i]的位置,
                    // dp[i][j-weight[i]]与该行左侧的值息息相关。
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-weight[i]] + value[i]);
                }
                // 如果容量不够放入新的物品,则从上一行继承
                else if(j < weight[i])   dp[i][j] = dp[i-1][j];
            }
        }
        System.out.println(dp[itemSize-1][bagSize]);
        
        // 打印dp数组
        for (int i = 0; i < itemSize; i++) {
            for (int j = 0; j <= bagSize; j++) {
                System.out.print(dp[i][j] + "\t");
            }
            System.out.println("\n");
        }
    }
}

完全背包问题 – 一维dp数组

  • 动态规划五步曲:
    ① 确定dp[j]的含义 : 任取[0, i]的物品(可重复使用)后放进容量为j的背包 所能放的 最大价值
    ② 求递推公式 : dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
    Ⅰ 不放物品 i : dp[j]
    Ⅱ 放物品 i : dp[j-weight[i]] + value[i]
    ③ dp数组如何初始化 : 初始化为0
    ④ 遍历顺序:先遍历物品,再遍历背包(正序),和01背包问题8同。

虽然下面的代码应该是没问题的,但是数字量变大之后会很容易超时。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //m,n分别代表物品种类和背包容量
        int itemSize = 0,bagSize = 0;
        Scanner sc = new Scanner(System.in);
        //获取itemSize和bagSize的值
        itemSize = sc.nextInt();
        bagSize = sc.nextInt();
        //初始化对应的重量数组和价值数组
        int[] weight = new int[itemSize];
        int[] value = new int[itemSize];
        //这两个都是物品的属性,大小只和物品数量有关
        for(int i = 0;i < itemSize;i++){
            weight[i] = sc.nextInt();
            value[i] = sc.nextInt();
        }
        
        // 完全背包问题
        testWeightBagProblem(weight,value,bagSize);
    }

    /**
     * 动态规划获得结果
     * @param weight  物品的重量
     * @param value   物品的价值
     * @param bagSize 背包的容量
     */
    public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){

        int itemSize = value.length;
        int[] dp = new int[bagSize+1];
        
        // 初始化为0
        
        // 递归推导
        for(int i = 0; i < itemSize; i++){
            for(int j = weight[i]; j < bagSize+1; j++){
                dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
                // System.out.print(dp[j] + "\t");
            }
            // System.out.println("\n");
        }
        
        System.out.print(dp[bagSize] + "\n");

    }
}

518.零钱兑换II

  • 动态规划五步曲:
    ① 确定dp[i]的含义 : 装满容量为i的背包有dp[i]种方法。
    ② 求递推公式 : dp[j] += dp[j - coins[i]] (装满背包的方法数的相关问题的统一递归公式)
    ③ dp数组如何初始化 : dp[0] = 1 (若dp[0] = 0,则所有的全部为0。)
    ④ 确定遍历顺序 : 从前向后,先物品后背包
    ⑤ 打印dp数组
组合的dp数组
1 1 1 1 1
1 2 2 3 3
1 2 2 3 4

排列的dp数组
1 1 1
1 1 1
1 2 2
2 3 3
3 5 5
5 8 9
  • 一种记忆方法:先遍历物品(物品不会重复被取得)为组合
class Solution {
    public int change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        int itemSize = coins.length;

        // 初始化
        dp[0] = 1;

        // 递归推导
        for(int i = 0; i < itemSize; i++){
            // 先物品后背包就可以保证是组合而不是排列
            for(int j = coins[i]; j < amount+1; j++){
                // 因为减去coins[i]的面值,就是可以凑出的方法数。
                dp[j] += dp[j - coins[i]];
                System.out.println(dp[j]);
            }
            System.out.println("*");
        }

        // for(int j = 0; j < amount+1; j++){
        //     // 先背包后物品就可以保证是排列而不是组合
        //     // for(int j = i; j < amount+1; j++){
        //     for(int i = 0; i < itemSize; i++){
        //         // 因为减去coins[i]的面值,就是可以凑出的方法数。
        //         if(j - coins[i] >= 0)
        //             dp[j] += dp[j - coins[i]];
        //         System.out.println(dp[j]);
        //     }
        //     System.out.println("*");
        // }

        return dp[amount];
    }
}

377.组合总和IV

  • 动态规划五步曲:
    ① 确定dp[i]的含义 : 装满容量为i的背包有dp[i]种方法(排列)。
    ② 求递推公式 : dp[j] += dp[j - coins[i]] (装满背包的方法数的相关问题的统一递归公式)
    ③ dp数组如何初始化 : dp[0] = 1 (若dp[0] = 0,则所有的全部为0。)
    ④ 确定遍历顺序 : 从前向后,先背包后物品
    ⑤ 打印dp数组
class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target+1];
        int itemSize = nums.length;
        Arrays.sort(nums);

        // 初始化
        dp[0] = 1;

        // 递归推导
        for(int j = 0; j < target+1; j++){
            // 先背包后物品就可以保证是排列而不是组合
            for(int i = 0; i < itemSize && j >= nums[i] ; i++){
                // 因为减去coins[i]的面值,就是可以凑出的方法数。
                dp[j] += dp[j - nums[i]];
                // System.out.println(dp[j]);
            }
            // System.out.println("*");
        }

        return dp[target];
    }
}

学习时间:

  • 上午两个半小时,整理文档半小时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1291202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sklearn随机森林 测试 路面点云分类

一、特征5个坐标 坐标-特征-类别 训练数据 二、模型训练 记录分享给有需要的人&#xff0c;代码质量勿喷 import numpy as np import pandas as pd import joblib#region 1 读取数据 dir D:\\py\\RandomForest\\ filename1 trainRS filename2 .csv path dirfilename1file…

C# 图解教程 第5版 —— 第16章 接口

文章目录 16.1 什么是接口16.2 声明接口16.3 实现接口16.4 接口是引用类型16.5 接口和 as 运算符16.6 实现多个接口16.7 实现具有重复成员的接口16.8 多个接口的引用&#xff08;*&#xff09;16.9 派生成员作为实现&#xff08;*&#xff09;16.10 显示接口成员实现16.11 接口…

Matlab 曲线动态绘制

axes(handles.axes1); % 选定所画坐标轴 figure也可 h1 animatedline; h1.Color b; h1.LineWidth 2; h1.LineStyle -; % 线属性设置 for i 1 : length(x)addpoints(h1,x(i),y(i)); % x/y为待绘制曲线数据drawnow;pause(0.01); % 画点间停顿 end 示例&#xff1a; figure…

如何在Web应用中添加一个JavaScript Excel查看器

前言 在现代的Web应用开发中&#xff0c;Excel文件的处理和展示是一项常见的需求。为了提供更好的用户体验和功能&#xff0c;经常需要在Web应用中添加一个JavaScript Excel查看器&#xff0c;小编今天将为大家展示如何借助葡萄城公司的纯前端表格控件——SpreadJS来创建一个E…

Spark RDD惰性计算的自主优化

原创/朱季谦 RDD&#xff08;弹性分布式数据集&#xff09;中的数据就如final定义一般&#xff0c;只可读而无法修改&#xff0c;若要对RDD进行转换或操作&#xff0c;那就需要创建一个新的RDD来保存结果。故而就需要用到转换和行动的算子。 Spark运行是惰性的&#xff0c;在…

网络安全(四)--Linux 主机防火墙

7.1. 介绍 防火墙&#xff08;Firewall&#xff09;&#xff0c;也称防护墙&#xff0c;是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网&#xff08;US5606668&#xff08;A&#xff09;1993-12-15&#xff09;。 它是一种位于内部网络与外部网络之间的网络安全…

clickhouse数据库磁盘空间使用率过高问题排查

一、前言 clickhouse天天触发磁盘使用率过高告警&#xff0c;所以需要进行排查&#xff0c;故将排查记录一下。 二、排查过程 1、连接上进入clickhouse 2、执行语句查看各库表使用磁盘情况 SELECT database, table, formatReadableSize(sum(bytes_on_disk)) as disk_space F…

数据库加密产品都有哪些功能?

数据库加密产品的主要功能是保护数据库中的敏感数据&#xff0c;确保其机密性和完整性。以下是数据库加密产品可能具备的一些功能&#xff1a; 数据加密&#xff1a;对数据库中的敏感数据进行加密&#xff0c;使得未经授权的人员无法读取或篡改数据。加密算法可以包括对称加密、…

2024 年 20 款最佳免费视频转换器软件 [安全快速有效]

最佳视频转换器软件的功能和定价的回顾和比较。从顶级付费和免费在线视频转换器工具列表中选择&#xff0c;可以快速轻松地转换任何视频&#xff1a; 什么是视频转换器&#xff1f; 视频转换工具允许您将视频从一种格式转换为另一种格式。第一个商业上成功的视频格式是 Quad&…

面试官:说说webpack中常见的Loader?解决了什么问题?

面试官&#xff1a;说说webpack中常见的Loader&#xff1f;解决了什么问题&#xff1f; 一、是什么 loader 用于对模块的"源代码"进行转换&#xff0c;在 import 或"加载"模块时预处理文件 webpack做的事情&#xff0c;仅仅是分析出各种模块的依赖关系&a…

易宝OA 两处任意文件上传漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA系统UploadFile、BasicService.asmx等接口处存在文件上传漏洞,未授权的攻击者可…

【Docker】从零开始:17.Dockerfile基本概念

【Docker】从零开始&#xff1a;17.Dockerfile 概述1.什么是Dockerfile2.Dockerfile构建三大步骤3.Docker执行Dockerfile流程 一张图理解Dockerfile常用保留指令~FROM~~MAINTAINER~~RUN~两种格式 ~EXPOSE~~WORKDIR~~USER~~ENV~~ADD~~COPY~两种格式 ~VOLUME~~CMD~两种格式注意 ~…

【译】虚拟线程:绝对优势

原文地址&#xff1a;Virtual Threads: A Definite Advantage 一、前言 深入了解虚拟线程如何提高应用程序的性能和可扩展性&#xff0c;同时将线程管理开销降到最低。 探索虚拟线程是一件很棒的事情&#xff0c;它是 Java 的一项强大功能&#xff0c;有望彻底改变多线程应用…

【数据结构】—红黑树(C++实现)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; AVL树 ♈️今日夜电波&#xff1a;Letter Song—ヲタみん 1:36━━━━━━️&#x1f49f;──────── 5:35 …

编织魔法世界——计算机科学的奇幻之旅

文章目录 每日一句正能量前言为什么当初选择计算机行业计算机对自己人生道路的影响后记 每日一句正能量 人生就像赛跑&#xff0c;不在乎你是否第一个到达尽头&#xff0c;而在乎你有没有跑完全程。 前言 计算机是一个神奇的领域&#xff0c;它可以让人们创造出炫酷的虚拟世界…

上位机与PLC:ModbusTCP通讯之数据类型转换

前请提要: 从PLC读取的数值,不管是读正负整数还是正负浮点数,读取过来后都会变成UInt16,也就是Ushort类型 一、ushort(UInt16)转成 Int32 源代码方法: //ushort类型转Int32类型的方法private int ushortToInt32(ushort[] date, int start){//先进行判断,长度是否正确…

在线工具分享SQL转ElasticSearchDSL语句

&#x1f60a; 作者&#xff1a; 瓶盖子io &#x1f496; 主页&#xff1a; 瓶盖子io-CSDN博客

vuepress-----10、vssue使用

vssue使用 https://vssue.js.org/ 按照文档 https://vssue.js.org/zh/guide/github.html (opens new window) 操作 # 1、创建 OAuth application https://github.com/settings/applications/new (opens new window) # 2、安装插件 yarn add vssue/vuepress-plugin-vssue# 这…

系统调用过程

应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管&#xff0c;因此凡是与共享资源有关的操作&#xff08;如存储分配、/O操作、文件管理等&#xff09;&#xff0c;都必须通过系统调用的方式向操作系统内核提出服务请求&#xff0c;由…

基于javaweb实现的学籍管理系统

一、 系统架构 前端&#xff1a;jsp | jquery | css 后端&#xff1a;servlet | jstl | sqljdbc 环境&#xff1a;jdk1.6 | mysql 二、代码及数据库 三、功能介绍 01. 登录页 02. 首页 03. 修改个人密码 04. 专业信息管理 05. 班级信息管理 06. 课程信息管理 07. 学籍…