代码随想录算法训练营第四十六天| 139.单词拆分,关于多重背包,你该了解这些!, 背包问题总结篇!

本文主要是介绍代码随想录算法训练营第四十六天| 139.单词拆分,关于多重背包,你该了解这些!, 背包问题总结篇!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 题目与题解

参考资料:背包问题总结

139.单词拆分

题目链接:139.单词拆分

代码随想录题解:139.单词拆分

视频讲解:动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili

解题思路:

        转换为背包问题,单词数组是可以放入背包的物品,字符串是背包,单词可以无限取,所以是完全背包问题,又因为单词是有顺序的,所以该题是求排列。

        但写的时候就很懵了,因为这里不是计算价值,也不是计算重量,没有办法直接将其value相加,不知道该咋写,只能看答案。

看完代码随想录之后的想法 

        首先还是要明确,dp的含义一般就是题目要求的结果。所以这题,dp数组表示当字符串长度为dp[i]时,是否存在符合条件的单词组合,存在则为true。

        由于是排列,所以应该先遍历背包(i),后遍历物品(j),递推公式为:当dp[j]为true,表示字符串长度为j时存在单词组合,所以只需要查询substr(j,i)的子字符串是否在单词数组中存在,存在则将当前dp[i]置为true。

        初始化dp[0]必须为true,否则dp计算出来永远为false。

class Solution {public boolean wordBreak(String s, List<String> wordDict) {boolean[] dp = new boolean[s.length()+1];dp[0] = true;for (int i = 1; i < dp.length; i++) {for (int j = 0; j < i; j++) {String substr = s.substring(j, i);if (dp[j] && wordDict.contains(substr)) {dp[i] = true;break;}}}return dp[s.length()];}
}

遇到的困难

        dp的定义一开始没有理清楚,虽然知道是完全背包的排列问题,但是没有想到用子字符串作为计算的方法。好难。

关于多重背包,你该了解这些!

题目链接:关于多重背包,你该了解这些!

代码随想录题解:关于多重背包,你该了解这些!

解题思路:

        多重背包就是01背包的升级版,只要把多个重量和价值相同的物品当作01背包里面多个不同的物品就可以了,同样用01背包的思路来做,只不过遍历的时候要多加一个对物品数量的遍历。

public class ID56Kama {public static void main (String[] args) {Scanner scanner = new Scanner(System.in);int C = scanner.nextInt();int N = scanner.nextInt();int[] w = new int[N];int[] v = new int[N];int[] k = new int[N];for (int i = 0; i < N; i++) {w[i] = scanner.nextInt();}for (int i = 0; i < N; i++) {v[i] = scanner.nextInt();}for (int i = 0; i < N; i++) {k[i] = scanner.nextInt();}int[] dp = new int[C+1];for (int i = 0; i < N; i++) {for (int k1 = 0; k1 < k[i]; k1++) {for (int j = C; j >= w[i]; j--) {dp[j] = Math.max(dp[j], dp[j-w[i]] + v[i]);}}}System.out.println(dp[C]);}
}

看完代码随想录之后的想法 

        随想录计算时用相乘代替累加,本质是一样的。

import java.util.Scanner;
class multi_pack{public static void main(String [] args) {Scanner sc = new Scanner(System.in);/*** bagWeight:背包容量* n:物品种类*/int bagWeight, n;//获取用户输入数据,中间用空格隔开,回车键换行bagWeight = sc.nextInt();n = sc.nextInt();int[] weight = new int[n];int[] value = new int[n];int[] nums = 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();for (int i = 0; i < n; i++) nums[i] = sc.nextInt();int[] dp = new int[bagWeight + 1];//先遍历物品再遍历背包,作为01背包处理for (int i = 0; i < n; i++) {for (int j = bagWeight; j >= weight[i]; j--) {//遍历每种物品的个数for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}System.out.println(dp[bagWeight]);}
}

遇到的困难

        01背包已经忘记了,复习一下。

今日收获

        巩固了一下背包问题。

        基础是动态规划五部曲:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

        背包问题常见的递归公式有以下几种:

问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,对应题目如下:

  • 动态规划:416.分割等和子集(opens new window)
  • 动态规划:1049.最后一块石头的重量 II(opens new window)

问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下:

  • 动态规划:494.目标和(opens new window)
  • 动态规划:518. 零钱兑换 II(opens new window)
  • 动态规划:377.组合总和Ⅳ(opens new window)
  • 动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,对应题目如下:

  • 动态规划:474.一和零(opens new window)

问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,对应题目如下:

  • 动态规划:322.零钱兑换(opens new window)
  • 动态规划:279.完全平方数

遍历顺序

01背包 / 多重背包

        二维:先遍历背包或先遍历物品都可以,从小到大遍历

        一维:先遍历物品后遍历背包,遍历背包时为了防止更新异常需要从大到小遍历。

完全背包:

        普通问题(如求最大或最小数):先遍历背包或先遍历物品都可以,从小到大遍历

        求组合数:先遍历物品后遍历背包

        求排列数:先遍历背包后遍历物品

这篇关于代码随想录算法训练营第四十六天| 139.单词拆分,关于多重背包,你该了解这些!, 背包问题总结篇!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924365

相关文章

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决