有依赖的的动态规划问题

题目

在这里插入图片描述
在这里插入图片描述

题型分析

这是比较典型的动态规划的问题。动态规划是什么呢?本质上动态规划是对递归的优化。例如,兔子数列:f(x) = f(x - 1) + f(x -2), 我们知道 f 代表了计算公式,这里解放思想一下,如果 f 替换为数组,将每个 f(x) 的返回值返回,那么是不是就不用计算了,直接返回了,这样就节省了 CPU 递归和计算的时间,提高计算的效率,这样就对递归进行了优化。

public static fb(int input){if(input == 1){return 1 ;}if(input == 2){return 2 ;}return fb(input -1) + fb(input - 2);
}

改成动态规划:

public static fb(int input){int[] dp = new int[input + 1];dp[1] = 1 ;dp[2] = 2 ;for(int i = 3 ; i <= input ; i++){dp[i] = dp[i - 1] + dp[i - 2] ;}return dp[input] ;
}

斐波那契数列只是一个数列而已。只是我们可以从中总结出一些规律:

  1. 找到初始值。这就是递归的出口。
  2. 然后以初始值为起点,往后继续计算。这代表了各个递归调用。

说完斐波那契数列,我们可以把难度增加。经典的 0-1 背包问题。它题目往往是这样有两个一维数组,第一个代表了容量,第二个代表价值,给定一个 N 正整数值,N 值是背包能装的容量,数组的一个元素代表了一个物品,一个物品只能装一个,问背包能装下的最大价值是多少?
递归的算法:
定义 process(int i , int N , int[][] capacity , int[][] value) , 其中 i 代表 i ~ capacity.length 容量为 N 的情况下,返回最大的价值。
于是可以按两种情况处理。

  1. 不要 i 物品, 那么递归应该 process(i , N ) = process(i + 1 , N)
  2. 要 i 物品,那么递归应该 process(i , N) = value[i] + process(i + 1 , N - capacity[i])
  3. 然后取里面最大的那个。

有了上面的分析,递归可以写为:

    public static int process(int[] weight, int[] value, int startIdx, int bagWeight) {if (startIdx == weight.length - 1) {return (weight[startIdx] <= bagWeight ? value[startIdx] : 0);}if (bagWeight == 0) {return 0;}// 不将 startIdx 的物品放入背包int v1 = process(weight, value, startIdx + 1, bagWeight);int v2 = 0;if (bagWeight >= weight[startIdx]) {v2 = process(weight, value, startIdx + 1, bagWeight - weight[startIdx])+ value[startIdx];}return Math.max(v2, v1);}

同样的如果将 process 看成是数组,那么可以想象:

  1. 可以先计算出 dp[capacity.length -1 ][0 … N] 的初始中,代表的业务含义是当容量从 0 到 N 时的最大价值。
  2. 我们可以看出 i 的值是依赖于 i + 1 的值,所以 dp[capacity.length - 2 ][0 … N] 也可以计算出来,一次类推,数组的所有需要的值都可以计算出来。
  3. 最后返回的是 dp[0][N] 的值就可以了。

于是动态规划的版本如下所示:

public static int processWithDp(int[] w , int[] v , int bag){int[][] dp = new int[w.length+1][bag+1];int p1 = 0 ;int p2 = 0 ;for(int index = w.length - 1 ; index >=0  ; index--){for(int rest = 0 ; rest <= bag ; rest++){p1 = dp[index+1][rest];p2 = 0 ;if(rest >= w[index]){p2 = dp[index+1][rest - w[index]] + v[index];}dp[index][rest] =  Math.max(p1 , p2);}}return dp[0][bag] ;}

最后说到这个题目,此题是在 0-1 背包的基础上增加了依赖。从题目中,可以知道附件不能离开主件独立存在,所以可以先以主件分组,A1{main , fj1 , fj2 } , A2{main , fj1 , fj2} … 在计算的时候,取下面的最大值。

  1. 不要 i 主件物品, A(i , N) = A(i +1 , N)
  2. 只要 i 主件物品,A(i , N) = A(i + 1 , N - A(i)的价格)
  3. 只要 i 主件、fj1, A(i , N) = A(i + 1 , N - A(i)的价格 - fj1 的价格)
  4. 只要 i 主件、fj2, A(i , N) = A(i + 1 , N - A(i)的价格 - fj2 的价格)
  5. i 主件、fj1、fj2, A(i , N) = A(i + 1 , N - A(i)的价格 - fj1 的价格 - fj2 的价格)

根据这样的理解,编写如下代码:

import java.util.*;  // 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别int N = 0 ; int m = 0 ;List<Product> products = new ArrayList();if(in.hasNextInt()) { // 注意 while 处理多个 caseN = in.nextInt();m = in.nextInt();}for(int a = 1 ; a <= m ; a++){products.add(new Product(a ,in.nextInt() , in.nextInt() , in.nextInt()));}int[][] value = new int[products.size()][3];int[][] price = new int[products.size()][3];List<Product> main = component(value , price , products);System.out.println(maxSatisfiedSocre2(N , main , value , price));}public static  List<Product> component(int[][] value , int[][] price , List<Product> products){List<Product> main = new ArrayList();int j = 0 ;for(int i = 0 ; i < products.size() ; i++){if(products.get(i).q == 0){main.add(products.get(i));value[j][0] = products.get(i).v;price[j][0] = products.get(i).p;List<Product> c = getFj(products.get(i).idx , products);if(c.size() > 0){value[j][1] = c.get(0).p;price[j][1] = c.get(0).v;if(c.size() > 1 ){value[j][2] = c.get(1).p;price[j][2] = c.get(1).v;}}j++;}}return main ;}public static List<Product> getFj(int id , List<Product> products){List<Product> rs = new ArrayList<Product>();for(int i = 0 ; i < products.size() ; i++){if(id == products.get(i).q){rs.add(products.get(i));}}return rs ;}public static class Product{public int idx ;public int v ;public int p ;public int q ;public Product(int idx ,int v , int p , int q){this.idx = idx ;this.v = v ;this.p = p ;this.q = q ;}}// 递归版本,此解法会超时public static int maxSatisfiedSocre(int N ,List<Product> products , int[][] value , int[][] price){if(N == 0 || null == products || products.size() == 0) return 0 ;return process(0 , N , products , value , price);}// 动态递归的解法public static int maxSatisfiedSocre2(int N ,List<Product> products , int[][] value , int[][] price){if(N == 0 || null == products || products.size() == 0) return 0 ;int[][] dp = new int[products.size()][N+1];int p1 = -1 ;int p2 = -1 ;int p3 = -1 ;int p4 = -1 ;int idx = products.size()-1 ;// int j = N ;for(int j = N ; j >= products.get(idx).v ; j-- ){p1 = -1 ;p2 = -1 ;p3 = -1 ;p4 = -1 ;if( j >= products.get(idx).v){p1 = products.get(idx).v*products.get(idx).p ;// dp[idx][j - products.get(idx).v] = p1 ;}if(j >= products.get(idx).v + price[idx][1]){p2 = products.get(idx).v*products.get(idx).p + value[idx][1]*price[idx][1] ;// dp[idx][j - products.get(idx).v - price[idx][1]] = p2 ;              }if(j >= products.get(idx).v + price[idx][2]){p3 = products.get(idx).v*products.get(idx).p + value[idx][2]*price[idx][2] ;// dp[idx][j - products.get(idx).v - price[idx][2]] = p3 ;              }if(j >= products.get(idx).v + price[idx][1] + price[idx][2]){p4 = products.get(idx).v*products.get(idx).p + value[idx][1]*price[idx][1] + value[idx][2]*price[idx][2] ;// dp[idx][j - products.get(idx).v - price[idx][1] - price[idx][2]] = p4 ;}dp[idx][j] = Math.max(Math.max(p1 , p2) , Math.max(p3 , p4));}int p5 = -1 ;for(int i = products.size() - 2 ; i>=0  ; i--){for(int j = N ; j > 0 ; j--){p1 = -1 ;p2 = -1 ;p3 = -1 ;p4 = -1 ;p5 = -1 ;if( j >= products.get(i).v ){p1 = products.get(i).v*products.get(i).p + dp[i+1][j - products.get(i).v];// dp[i][j - products.get(i).v] = p1 ;}if(j >= products.get(i).v + price[i][1]){p2 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] + dp[i+1][j - products.get(i).v - price[i][1]];// dp[i][j - products.get(i).v - price[i][1]] = p2;}if(j >= products.get(i).v + price[i][2]){p3 = products.get(i).v*products.get(i).p + value[i][2]*price[i][2] + dp[i+1][j - products.get(i).v - price[i][2]];// dp[i][j - products.get(i).v - price[i][2]] = p3 ;                 }if(j >= products.get(i).v + price[i][1] + price[i][2]){p4 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] + value[i][2]*price[i][2] + dp[i+1][j - products.get(i).v - price[i][1] - price[i][2]];// dp[i][j - products.get(i).v - price[i][1] - price[i][2] ] = p4 ;  }// 不要 ip5 = dp[i+1][j];dp[i][j] = Math.max(Math.max(p1 , p2) , Math.max(Math.max(p3 , p4) , p5));}}return dp[0][N];}// 递归版本的实际实现。public static int process(int i , int N , List<Product> products , int[][] value , int[][] price){if(i + 1 == products.size()){int p1 = -1 ;int p2 = -1 ;int p3 = -1 ;int p4 = -1 ;if( N >= products.get(i).v){p1 = products.get(i).v*products.get(i).p ;}if(N >= products.get(i).v + price[i][1]){p2 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] ;}if(N >= products.get(i).v + price[i][2]){p3 = products.get(i).v*products.get(i).p + value[i][2]*price[i][2] ;}if(N >= products.get(i).v + price[i][1] + price[i][2]){p4 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] + value[i][2]*price[i][2] ;}return Math.max(Math.max(p1 , p2) , Math.max(p3 , p4));}int p1 = -1 ;int p2 = -1 ;int p3 = -1 ;int p4 = -1 ;// 只要 i 的作为主键int next = process(i+1 , N - products.get(i).v , products , value , price);if(-1 == next){next = 0 ;}if( N >= products.get(i).v ){p1 = products.get(i).v*products.get(i).p + next ;}if(N >= products.get(i).v + price[i][1]){next = process(i+1 , N - products.get(i).v - price[i][1] , products , value , price);if(-1 == next){next = 0 ;}p2 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] + next ;}if(N >= products.get(i).v + price[i][2]){next = process(i+1 , N - products.get(i).v - price[i][2] , products , value , price);if(-1 == next){next = 0 ;}p3 = products.get(i).v*products.get(i).p + value[i][2]*price[i][2] + next;}if(N >= products.get(i).v + price[i][1] + price[i][2]){next = process(i+1 , N - products.get(i).v - price[i][1] - price[i][2] , products , value , price);if(-1 == next){next = 0 ;}p4 = products.get(i).v*products.get(i).p + value[i][1]*price[i][1] + value[i][2]*price[i][2] + next;}// 不要 iint p5 = process(i+1 , N , products , value , price);return Math.max(Math.max(p1 , p2) , Math.max(p5 , Math.max(p3 , p4)));}
}

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

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

相关文章

信息系统项目管理师——成本管理计算专题(一)

常见考点如下: ①问项目预算、BAC、成本基准、应急储备、管理储备的含义及它们之间的区别 ②给出成本基准和管理储备求项目预算&#xff0c;或者给出预算求成本基准等等 ③看图找 PV、AC、EV、SV、CV、BAC、EAC、ETC等 ④根据题干求项目的PV、AC、EV、SV、CV、BAC、EAC、ETC等 …

k8s高可用集群部署介绍 -- 理论

部署官网参考文档 负载均衡参考 官网两种部署模式拓扑图和介绍 介绍两种高可用模式 堆叠 拓扑图如下&#xff08;图片来自k8s官网&#xff09;&#xff1a; 特点&#xff1a;将etcd数据库作为控制平台的一员&#xff0c;由于etcd的共识算法&#xff0c;所以集群最少为3个&…

产业园区综合计费解决方案/预付费系统/用户侧能源计量及收费/无人值守远程抄表收费

安科瑞薛瑶瑶18701709087 园区管理的难点 ◆计费方式多样&#xff1a;园区类型多样&#xff0c;计费逻辑存在多样&#xff0c;工业电价、商业电价、两部制电价等 ◆缴费方式多样&#xff1a;租户性质不同&#xff0c;存在公对公&#xff0c;私对公&#xff0c;线下支付&…

LeetCode 73.矩阵置零————2024 春招冲刺百题计划

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 示例 2&#xff1a; 输入&#xff1a;matrix […

华为OD机试 - 连续天数的最高利润额(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

高效、稳定、兼容:中国星坤MINI PCIE连接器优势明显

电子设备的性能要求日益提高&#xff0c;尤其是在数据传输和连接稳定性方面。中国星坤推出的MINI PCIE连接器&#xff0c;以其出色的性能和显著的优势&#xff0c;迅速成为行业内的佼佼者&#xff0c;为现代电子设备提供了高效、稳定的连接解决方案。 在性能方面&#xff0c;中…

限制登录Linux服务器的几种方式

一.第一种方法 通过修改TCP Wrappers服务访问控制来实现限制登录Linux 1.这里以sshd服务为例&#xff0c;配置完成后&#xff0c;只允许配置允许的IP才能ssh连接本机服务器&#xff0c;其他IP拒绝判断某一个基于tcp协议的服务是否支持tcp_wrapper&#xff0c;要先判断它是否支…

登录页界面设计详细教程:打造令人印象深刻的用户登录体验

我们日常使用的软件都会有注册和登录页&#xff0c;为什么注册登录页面是必不可少的呢&#xff1f;对于企业&#xff0c;目的是将访客转化为产品用户&#xff0c;有助于获得用户画像和各种数据&#xff0c;针对用户的个性化服务进行产品的迭代更新。对于个人&#xff0c;则根据…

鸿蒙应用开发之下拉菜单选择组件

前面学习了搜索框组件,接着下来学习下位菜单选择组件。它实现了一个下拉式的菜单,当用户点击下拉菜单中某一项,就会被选中。 这个组件的界面大体如下: 这个组件可以设置每一项的图标,以及文本显示。由于它是下拉式的菜单,所以候选的内容建议不要太多,否则会滚动比较麻烦…

Redis-键值设计

Redis-键值设计 1.设置key的规范 遵循基本格式&#xff1a;【业务名称】&#xff1a;【数据名】&#xff1a;【id】 可读性强&#xff0c;在客户端的情况下使用:如果前缀相同会分目录层级长度不超过44字节 string数据结构的三种类型&#xff0c;在44字节之内是embstring 内存…

【零基础学数据结构】链表

目录 1.链表的概念 ​编辑 2.链表的雏形 ​编辑 3.链表的组成 ​编辑 4.链表代码 4.1创建节点 4.2链表的打印 4.3链表的尾插 4.4链表的头插 4.5链表的尾删 4.6链表的头删 4.7链表的查找 4.8链表在指定位置之前插⼊数据 4.9链表在指定位置之后插⼊数据 4.9-1删除pos节点 4.9…

做抖音小店保证金可以不交吗?不交保证金,会有什么后果?

哈喽~我是电商月月 说到最赚钱的软件&#xff0c;大家第一个想的就是抖音了&#xff0c;很多不想直播&#xff0c;但又想在抖音上赚钱的人就选择了抖音小店 但普通人创业&#xff0c;开店遇到的第一个困难就是类目保证金的缴纳 几千块钱虽然能拿的出来&#xff0c;但怕就怕在…

数据结构 -- 二分查找

本文主要梳理了二分查找算法的几种实现思路&#xff0c;基本概念参考 顺序、二分、哈希查找的区别及联系_生成一个大小为10万的有序数组,随机查找一个元素,分别采用顺序查找和二分查找方式-CSDN博客 1、基本概念 &#xff08;1&#xff09;前提条件&#xff1a;待查找数据必须…

java--包装类

目录 1、包装类的定义 2、意义 3、八大基本类型的包装类 4、转换 5、自动拆箱和自动装箱 6、面试问题&#xff1a;请阐述128陷阱以及出现的原因 1、包装类的定义 把基本类型包装--包装类 2、意义 1、在面向对象中&#xff0c;“一切皆为对象”&#xff0c;但是基本类型不…

fiddler使用(三)-工具栏介绍

Fiddler是一个强大的网络调试工具&#xff0c;它可以帮助用户捕获HTTP和HTTPS请求和响应&#xff0c;从而进行调试和分析。在Fiddler的用户界面中&#xff0c;工具栏是一个非常重要的组成部分&#xff0c;它提供了许多常用的操作和功能&#xff0c;方便用户进行网络调试。以下是…

布局香港之零售中小企篇 | 传承之味,迈向数字化经营的时代

随着内地与香港两地经贸合作日渐紧密&#xff0c;越来越多内地消费品牌将目光投向香港这片充满机遇的热土&#xff0c;纷纷入驻香港市场。「北店南下」蔚然成风&#xff0c;其中不乏已在内地市场深耕多年的传统老字号。数字化经营时代&#xff0c;老字号焕新刻不容缓&#xff0…

Git-常规用法-含解决分支版本冲突解决方法

目录 前置条件 已经创建了Gitee账号 创建一个远程仓库 Git的优点 版本控制 Git 下载 Git的使用 检查Git的是否安装成功 git的常用命令 常用流程 Git 分支 分支流程 Git 远程仓库 远程仓库流程 特殊 可能遇到的问题 前置条件 已经创建了Gitee账号 创建一个远程仓…

求1000以内正整数的平方根(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>int main() {//初始化变量值&#xff1b;int number 0;int result 0;//提示用户&#xff1b;printf("请输入1000以内求平方根的…

【c++leetcode】14. Longest Common Prefix

问题入口 解决方案 class Solution { public:string longestCommonPrefix(vector<string>& v) {string ans "";sort(v.begin(), v.end());int n v.size();string first v[0],last v[n - 1];for(int i 0; i < min(first.size(),last.size()); i){…

密码学 | 椭圆曲线数字签名方法 ECDSA(下)

目录 10 ECDSA 算法 11 创建签名 12 验证签名 13 ECDSA 的安全性 14 随机 k 值的重要性 15 结语 ⚠️ 原文&#xff1a;Understanding How ECDSA Protects Your Data. ⚠️ 写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留着学习。同时&#xff0c;经过几…