分组背包--完全背包

分组背包:多个物品分组,每组只能取1件

每一组的物品都可能性展开就可以,时间复杂度为O(物品的数量*背包的容量)

分组背包

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;public class Main {public static int MAXN = 1001;public static int MAXM = 1001;// arr[i][0] i号物品的体积// arr[i][1] i号物品的价值// arr[i][2] i号物品的组号public static int[][] arr = new int[MAXN][3];public static int[] dp = new int[MAXM];public static int m, n;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {m = (int) in.nval;in.nextToken();n = (int) in.nval;for (int i = 1; i <= n; i++) {in.nextToken();arr[i][0] = (int) in.nval;in.nextToken();arr[i][1] = (int) in.nval;in.nextToken();arr[i][2] = (int) in.nval;}Arrays.sort(arr, 1, n + 1, (a, b) -> a[2] - b[2]);out.println(compute1());}out.flush();out.close();br.close();}// 严格位置依赖的动态规划public static int compute1() {int teams = 1;for (int i = 2; i <= n; i++) {if (arr[i - 1][2] != arr[i][2]) {teams++;}}// 组的编号1~teams// dp[i][j] : 1~i是组的范围,每个组的物品挑一件,容量不超过j的情况下,最大收益int[][] dp = new int[teams + 1][m + 1];// dp[0][....] = 0for (int start = 1, end = 2, i = 1; start <= n; i++) {while (end <= n && arr[end][2] == arr[start][2]) {end++;}// start ... end-1 -> i组for (int j = 0; j <= m; j++) {// arr[start...end-1]是当前组,组号一样// 其中的每一件商品枚举一遍dp[i][j] = dp[i - 1][j];for (int k = start; k < end; k++) {// k是组内的一个商品编号if (j - arr[k][0] >= 0) {dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - arr[k][0]] + arr[k][1]);}}}// start去往下一组的第一个物品// 继续处理剩下的组start = end++;}return dp[teams][m];}// 空间压缩public static int compute2() {// dp[0][...] = 0Arrays.fill(dp, 0, m + 1, 0);for (int start = 1, end = 2; start <= n;) {while (end <= n && arr[end][2] == arr[start][2]) {end++;}// start....end-1for (int j = m; j >= 0; j--) {for (int k = start; k < end; k++) {if (j - arr[k][0] >= 0) {dp[j] = Math.max(dp[j], arr[k][1] + dp[j - arr[k][0]]);}}}start = end++;}return dp[m];}}

从栈中取出k个硬币的最大面值和

    // piles是一组一组的硬币// m是容量,表示一定要进行m次操作// dp[i][j] : 1~i组上,一共拿走j个硬币的情况下,获得的最大价值// 1) 不要i组的硬币 : dp[i-1][j]// 2) i组里尝试每一种方案// 比如,i组里拿走前k个硬币的方案 : dp[i-1][j-k] + 从顶部开始前k个硬币的价值和// 枚举每一个k,选出最大值  
class Solution {public static int maxValueOfCoins(List<List<Integer>> piles, int m) {int n = piles.size();int[][] dp = new int[n + 1][m + 1];for (int i = 1; i <= n; i++) {// i从1组开始(我们的设定),但是题目中的piles是从下标0开始的// 所以来到i的时候,piles.get(i-1)是当前组List<Integer> team = piles.get(i - 1);int t = Math.min(team.size(), m);// 预处理前缀和,为了加速计算int[] preSum = new int[t + 1];for (int j = 0, sum = 0; j < t; j++) {sum += team.get(j);preSum[j + 1] = sum;}// 更新动态规划表for (int j = 0; j <= m; j++) {// 当前组一个硬币也不拿的方案dp[i][j] = dp[i - 1][j];for (int k = 1; k <= Math.min(t, j); k++) {dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k] + preSum[k]);}}}return dp[n][m];}// 空间压缩public static int maxValueOfCoins2(List<List<Integer>> piles, int m) {int[] dp = new int[m + 1];for (List<Integer> team : piles) {int t = Math.min(team.size(), m);int[] preSum = new int[t + 1];for (int j = 0, sum = 0; j < t; j++) {sum += team.get(j);preSum[j + 1] = sum;}for (int j = m; j > 0; j--) {for (int k = 1; k <= Math.min(t, j); k++) {dp[j] = Math.max(dp[j], dp[j - k] + preSum[k]);}}}return dp[m];}}

把每个栈中取出硬币的情况装到一个数组中,展开讨论即可

完全背包:每种商品可以选取无限次。时间复杂度为(物品数量*背包容量)

完全背包

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;public class Code03_UnboundedKnapsack {public static int MAXM = 10001;public static int MAXT = 10000001;public static int[] cost = new int[MAXM];public static int[] val = new int[MAXM];public static long[] dp = new long[MAXT];public static int t, m;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {t = (int) in.nval;in.nextToken();m = (int) in.nval;for (int i = 1; i <= m; i++) {in.nextToken();cost[i] = (int) in.nval;in.nextToken();val[i] = (int) in.nval;}out.println(compute2());}out.flush();out.close();br.close();}// 严格位置依赖的动态规划// 会空间不够,导致无法通过全部测试用例public static long compute1() {// dp[0][.....] = 0int[][] dp = new int[m + 1][t + 1];for (int i = 1; i <= m; i++) {for (int j = 0; j <= t; j++) {dp[i][j] = dp[i - 1][j];if (j - cost[i] >= 0) {dp[i][j] = Math.max(dp[i][j], dp[i][j - cost[i]] + val[i]);}}}return dp[m][t];}// 空间压缩// 可以通过全部测试用例public static long compute2() {Arrays.fill(dp, 1, t + 1, 0);for (int i = 1; i <= m; i++) {for (int j = cost[i]; j <= t; j++) {dp[j] = Math.max(dp[j], dp[j - cost[i]] + val[i]);}}return dp[t];}}

正则表达式匹配

public class Solution {public static boolean isMatch(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();return f1(s, p, 0, 0);}// s[i....]能不能被p[j....]完全匹配出来// p[j]这个字符,一定不是'*'public static boolean f1(char[] s, char[] p, int i, int j) {if (i == s.length) {// s没了if (j == p.length) {// 如果p也没了,返回truereturn true;} else {// p还剩下一些后缀// 如果p[j+1]是*,那么p[j..j+1]可以消掉,然后看看p[j+2....]是不是都能消掉return j + 1 < p.length && p[j + 1] == '*' && f1(s, p, i, j + 2);}} else if (j == p.length) {// s有后缀// p没后缀了return false;} else {// s有后缀// p有后缀if (j + 1 == p.length || p[j + 1] != '*') {// s[i....]// p[j....]// 如果p[j+1]不是*,那么当前的字符必须能匹配:(s[i] == p[j] || p[j] == '?')// 同时,后续也必须匹配上:process1(s, p, i + 1, j + 1);return (s[i] == p[j] || p[j] == '.') && f1(s, p, i + 1, j + 1);} else {// 如果p[j+1]是*// 完全背包!// s[i....]// p[j....]// 选择1: 当前p[j..j+1]是x*,就是不让它搞定s[i],那么继续 : process1(s, p, i, j + 2)boolean p1 = f1(s, p, i, j + 2);// 选择2: 当前p[j..j+1]是x*,如果可以搞定s[i],那么继续 : process1(s, p, i + 1, j)// 如果可以搞定s[i] : (s[i] == p[j] || p[j] == '.')// 继续匹配 : process1(s, p, i + 1, j)boolean p2 = (s[i] == p[j] || p[j] == '.') && f1(s, p, i + 1, j);// 两个选择,有一个可以搞定就返回true,都无法搞定返回falsereturn p1 || p2;}}}// 记忆化搜索public static boolean isMatch2(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();int n = s.length;int m = p.length;// dp[i][j] == 0,表示没算过// dp[i][j] == 1,表示算过,答案是true// dp[i][j] == 2,表示算过,答案是falseint[][] dp = new int[n + 1][m + 1];return f2(s, p, 0, 0, dp);}public static boolean f2(char[] s, char[] p, int i, int j, int[][] dp) {if (dp[i][j] != 0) {return dp[i][j] == 1;}boolean ans;if (i == s.length) {if (j == p.length) {ans = true;} else {ans = j + 1 < p.length && p[j + 1] == '*' && f2(s, p, i, j + 2, dp);}} else if (j == p.length) {ans = false;} else {if (j + 1 == p.length || p[j + 1] != '*') {ans = (s[i] == p[j] || p[j] == '.') && f2(s, p, i + 1, j + 1, dp);} else {ans = f2(s, p, i, j + 2, dp) || ((s[i] == p[j] || p[j] == '.') && f2(s, p, i + 1, j, dp));}}dp[i][j] = ans ? 1 : 2;return ans;}// 严格位置依赖的动态规划public static boolean isMatch3(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();int n = s.length;int m = p.length;boolean[][] dp = new boolean[n + 1][m + 1];dp[n][m] = true;for (int j = m - 1; j >= 0; j--) {dp[n][j] = j + 1 < m && p[j + 1] == '*' && dp[n][j + 2];}for (int i = n - 1; i >= 0; i--) {for (int j = m - 1; j >= 0; j--) {if (j + 1 == m || p[j + 1] != '*') {dp[i][j] = (s[i] == p[j] || p[j] == '.') && dp[i + 1][j + 1];} else {dp[i][j] = dp[i][j + 2] || ((s[i] == p[j] || p[j] == '.') && dp[i + 1][j]);}}}return dp[0][0];}}

通配符匹配

public class Solution {// 暴力递归public static boolean isMatch1(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();return f1(s, p, 0, 0);}// s[i....]能不能被p[j....]完全匹配出来public static boolean f1(char[] s, char[] p, int i, int j) {if (i == s.length) {// s没了if (j == p.length) {// 如果p也没了,返回truereturn true;} else {// 如果p[j]是*,可以消掉,然后看看p[j+1....]是不是都能消掉return p[j] == '*' && f1(s, p, i, j + 1);}} else if (j == p.length) {// s有// p没了return false;} else {if (p[j] != '*') {// s[i....]// p[j....]// 如果p[j]不是*,那么当前的字符必须能匹配:(s[i] == p[j] || p[j] == '?')// 同时,后续也必须匹配上:process1(s, p, i + 1, j + 1);return (s[i] == p[j] || p[j] == '?') && f1(s, p, i + 1, j + 1);} else {// s[i....]// p[j....]// 如果p[j]是*// 选择1: 反正当前p[j]是*,必然可以搞定s[i],那么继续 : process1(s, p, i + 1, j)// 选择2: 虽然当前p[j]是*,但就是不让它搞定s[i],那么继续 : process1(s, p, i, j + 1)// 两种选择有一个能走通,答案就是true;如果都搞不定,答案就是falsereturn f1(s, p, i + 1, j) || f1(s, p, i, j + 1);}}}// 记忆化搜索public static boolean isMatch2(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();int n = s.length;int m = p.length;// dp[i][j] == 0,表示没算过// dp[i][j] == 1,表示算过,答案是true// dp[i][j] == 2,表示算过,答案是falseint[][] dp = new int[n + 1][m + 1];return f2(s, p, 0, 0, dp);}public static boolean f2(char[] s, char[] p, int i, int j, int[][] dp) {if (dp[i][j] != 0) {return dp[i][j] == 1;}boolean ans;if (i == s.length) {if (j == p.length) {ans = true;} else {ans = p[j] == '*' && f2(s, p, i, j + 1, dp);}} else if (j == p.length) {ans = false;} else {if (p[j] != '*') {ans = (s[i] == p[j] || p[j] == '?') && f2(s, p, i + 1, j + 1, dp);} else {ans = f2(s, p, i + 1, j, dp) || f2(s, p, i, j + 1, dp);}}dp[i][j] = ans ? 1 : 2;return ans;}// 严格位置依赖的动态规划public static boolean isMatch(String str, String pat) {char[] s = str.toCharArray();char[] p = pat.toCharArray();int n = s.length;int m = p.length;boolean[][] dp = new boolean[n + 1][m + 1];dp[n][m] = true;for (int j = m - 1; j >= 0 && p[j] == '*'; j--) {dp[n][j] = true;}for (int i = n - 1; i >= 0; i--) {for (int j = m - 1; j >= 0; j--) {if (p[j] != '*') {dp[i][j] = (s[i] == p[j] || p[j] == '?') && dp[i + 1][j + 1];} else {dp[i][j] = dp[i + 1][j] || dp[i][j + 1];}}}return dp[0][0];}}

购买干草的最小花费

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;public class Main {public static int MAXN = 101;public static int MAXM = 55001;public static int[] val = new int[MAXN];public static int[] cost = new int[MAXN];public static int[] dp = new int[MAXM];public static int n, h, maxv, m;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {n = (int) in.nval;in.nextToken();h = (int) in.nval;maxv = 0;for (int i = 1; i <= n; i++) {in.nextToken();val[i] = (int) in.nval;maxv = Math.max(maxv, val[i]);in.nextToken();cost[i] = (int) in.nval;}// 最核心的一句// 包含重要分析m = h + maxv;out.println(compute1());}out.flush();out.close();br.close();}// dp[i][j] : 1...i里挑公司,购买严格j磅干草,需要的最少花费// 1) dp[i-1][j]// 2) dp[i][j-val[i]] + cost[i]// 两种可能性中选最小// 但是关于j需要进行一定的扩充,原因视频里讲了public static int compute1() {int[][] dp = new int[n + 1][m + 1];Arrays.fill(dp[0], 1, m + 1, Integer.MAX_VALUE);for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++) {dp[i][j] = dp[i - 1][j];if (j - val[i] >= 0 && dp[i][j - val[i]] != Integer.MAX_VALUE) {dp[i][j] = Math.min(dp[i][j], dp[i][j - val[i]] + cost[i]);}if(j-val[i]<0&&dp[i][0]!=Integer.MAX_VALUE)dp[i][j]=Math.min(dp[i][j],dp[i][0]+cost[i]);}}int ans = Integer.MAX_VALUE;// >= h// h h+1 h+2 ... mfor (int j = h; j <= m; j++) {ans = Math.min(ans, dp[n][j]);}return dp[n][h];}// 空间压缩public static int compute2() {Arrays.fill(dp, 1, m + 1, Integer.MAX_VALUE);for (int i = 1; i <= n; i++) {for (int j = val[i]; j <= m; j++) {if (dp[j - val[i]] != Integer.MAX_VALUE) {dp[j] = Math.min(dp[j], dp[j - val[i]] + cost[i]);}}}int ans = Integer.MAX_VALUE;for (int j = h; j <= m; j++) {ans = Math.min(ans, dp[j]);}return ans;}}

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

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

相关文章

基于微信小程序+SpringBoot+Vue的垃圾分类系统(带1w+文档)

基于微信小程序SpringBootVue的垃圾分类系统(带1w文档) 基于微信小程序SpringBootVue的垃圾分类系统(带1w文档) 本垃圾分类小程序也是紧跟科学技术的发展&#xff0c;运用当今一流的软件技术实现软件系统的开发&#xff0c;让环保方面的信息完全通过管理系统实现科学化&#xf…

【Jackson】注解及其使用

Jackson库提供了多种注解&#xff08;annotations&#xff09;&#xff0c;可以用来控制JSON序列化和反序列化的行为。这些注解允许你灵活地映射Java对象与JSON数据之间的关系。下面将详细介绍一些常用的Jackson注解及其用法。 1. JsonProperty 作用: 用于指定JSON属性与Java…

不是演练 “毒云藤”再出击,知网用户成钓鱼攻击目标

亚信安全威胁情报中心近期在梳理安全事件时&#xff0c;发现一起钓鱼攻击活动。该起事件仿冒网易云邮箱进行钓鱼攻击&#xff0c;成功窃取到用户信息后将用户信息post到本地的”login.php”目录下保存&#xff0c;并跳转到正常网站。经分析&#xff0c;判断该行为符合绿斑APT组…

React: 条码渲染 渲染列表

一、条件渲染 1、定义&#xff1a;根据不同的情况显示不同的内容&#xff08;就像vue中的v-if)。 2、在 React 中&#xff0c;可以使用 JavaScript 的 if 语句、&& 和 ? : 运算符来选择性地渲染 JSX。 2.1 使用条件判断&#xff08;if&#xff09; export default f…

FastAPI(八十二)实战开发《在线课程学习系统》接口开发-- 课程上架下架

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 课程上架/下架 1、是否登录 2、角色权限 3、课程是否存在 4、是否是自己的课程 4、课程如果是上架状态&#xff0c;则下架&#xff0c;反之&#xff…

【Python第三方库】PyQt5安装与应用

文章目录 引言安装PYQT5基于Pyqt5的简单桌面应用常用的方法与属性QtDesigner工具使用与集成窗口类型QWidget和QMainWindow区别 UI文件加载方式直接加载UI文件的方式显示窗口转化py文件进行显示窗口 PyQt5中常用的操作信号与槽的设置绑定页面跳转 引言 PyQt5是一个流行的Python…

AutoSar中的Spi_SetupEB函数原理与实现

文章目录 一、函数介绍二、项目背景三、函数在AUTOSAR官网中的介绍四、代码实现五、验证六、联调过程中遇到的问题 一、函数介绍 此函数是Autosar标准中的接口&#xff0c;为EB SPI处理器/驱动程序设置缓冲区和数据长度的服务 指定频道。用容易理解的话说就是 设置一下某个通道…

人工智能在教育领域的应用:优势、挑战与未来展望

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正以其独特的方式重塑教育的面貌。从课堂互动到个性化学习&#xff0c;再到教学管理&#xff0c;AI技术的应用正变得越来越广泛。本文将深入探讨AI在教育领域的应用&#xff0c;分析其优势、挑战&#xff0c;并展望…

VUE3 el-table-column header新增必填*

1.在需要加必填星号的el-table-column上添加render-header属性 <el-table-column :label"getName(产品代码)" :render-header"addRedStart" prop"MODELCODE" min-width“4.5%”> <template v-slot"scope"> <el-input …

SpringBoot中使用监听器

1.定义一个事件 /*** 定义事件* author hrui* date 2024/7/25 12:46*/ public class CustomEvent extends ApplicationEvent {private String message;public CustomEvent(Object source, String message) {super(source);this.message message;}public String getMessage() …

Cannot find module ‘html-webpack-plugin

当你在使用Webpack构建项目时遇到Cannot find module html-webpack-plugin这样的错误&#xff0c;这意味着Webpack在构建过程中找不到html-webpack-plugin模块。要解决这个问题&#xff0c;你需要确保已经正确安装了html-webpack-plugin模块&#xff0c;并且在Webpack配置文件中…

uniapp手写滚动选择器

文章目录 效果展示HTML/Template部分&#xff1a;JavaScript部分&#xff1a;CSS部分&#xff1a;完整代码 没有符合项目要求的选择器 就手写了一个 效果展示 实现一个时间选择器的功能&#xff0c;可以选择小时和分钟&#xff1a; HTML/Template部分&#xff1a; <picker…

『 Linux 』信号概念与信号的产生 ( 万字 )

文章目录 信号概念前台进程与后台进程信号的本质硬件理解信号的产生Core dump 标志 信号概念 "信号"一词指用来传达信息或只是的各种形式的提示或标志; 在生活中常见的信号例如红绿灯,交通标志,短信通知等 在操作系统中,"信号"是一种用于异步通知进程发生特…

[嵌入式英语]Real Time Clock

zynqmpsoc 开发手册 Real Time Clock 章节 Introduction The real time clock (RTC) unit maintains an accurate time base for system and application software. For high accuracy needs, the RTC also includes calibration circuitry to offset temperature and voltage …

JVM加载一个实现了某个接口

在Java虚拟机&#xff08;JVM&#xff09;加载类和接口时&#xff0c;加载过程本身是由多个线程来完成的&#xff0c;而不是由单个线程完成的。JVM是多线程的&#xff0c;它可以并行加载多个类和接口&#xff0c;以提高加载效率和整体应用程序的性能。 具体来说&#xff0c;JV…

国衍科技——RFID技术的应用

在文物馆藏信息的记录与管理过程中&#xff0c;准确性和详细性是至关重要的。无论是大型博物馆还是私人收藏馆&#xff0c;都需要有效的方法来确保馆藏文物信息的可追溯性和可访问性&#xff0c;才能提供更好的服务和保护馆藏资源。而结合射频识别&#xff08;RFID&#xff09;…

2024年虚拟主机转移教程

转移网站并不困难&#xff0c;但选择正确的选项和最佳程序才是关键。网站托管服务被视为当今数字世界的基石&#xff0c;全球有18 亿个网站。网站所有者可以通过下载备份、将其上传到新服务器并指向域名来手动转移网站。他们还可以通过新网站托管商的助手请求来移动网站。对于初…

华清数据结构day5 24-7-22

1>使用栈&#xff0c;完成进制转换输入&#xff1a;一个整数&#xff0c;进制数输出&#xff1a;该数的对应的进制数 seqstack.h #ifndef SEQSTACK_H #define SEQSTACK_H #define MAX 10 #include"myhead.h" typedef int datatype;typedef struct {datatype *d…

【Tomcat】快速入门

概述 Tomcat是Apache软件基金会一个核心项目&#xff0c;是一个开源免费的轻量级Web服务器&#xff0c;支持Servlet/JSP.少量avaEE规范。Tomcat Tomcat也被称为Web容器、Servlet容器。Servleti程序需要依赖于Tomcat才能运行。 安装使用 下载安装都是绿色版本&#xff0c;解…

Git、Gitlab以及分支管理

分布式版本控制系统 一、Git概述 Git是一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更。它由Linus torvalds创建的&#xff0c;最初被设计用于Linux内核的开发。Git 允许开发人员跟踪和管理代码的版本&#xff0c;并且可以在不同的开发人员之间进行协作。 Githu…