动态规划-二维费用的背包问题

news2024/9/22 23:28:15

文章目录

  • 1. 一和零(474)
  • 2. 盈利计划(879)


1. 一和零(474)

题目描述:
在这里插入图片描述
状态表示:
我们之前的01背包问题以及完全背包问题都是一维的,因为我们只有一个要求或者说是限制那就是背包的容量,但是这里不同这题有两个限制,其实和一个限制是类似的,只不过给数组多加上一维而已。因此我们建立三维数组dp[i][j][k]表示我们在前i个二进制字符串中选择,要求选中的字符串中的0以及1字符的总数分别不能超过i以及j时strs最大子集的长度。
状态转移方程:
这题因为每个二进制字符串只能选一次,实际上就是01背包问题。我们对选择的第i个二进制字符串进行分析,如果不选择该字符串,那么dp[i][j][k]=dp[i-1][j][k].如果我们选择第i个二进制字符串,那么在j>=此二进制字符串0的个数时并且k>=此字符串中1的个数时,dp[i][j][k]=dp[i-1][j-此二进制字符串0的个数][k-此字符串中1的个数]+1。
初始化:
根据前面我们01背包以及完全背包的做题经验我们初始化会给ijk三个维度分别加上第0列/行(三维不知如何形容),对于j和k维度我们直接加入运算,不去考虑它初始化的问题,对于i维度的第0行因为此时意味着没有字符串,所以无论j、k维度如何要求最终数组的对应结果也就是字符串数组的对应的子集长度都是0,所以当i等于0时,j和k对应的平面上的dp值直接全赋为0即可。
填表顺序:
i维度下标从小到大进行运算,j和k维度随意。
返回值:
初始化dp数组时,ijk三个维度长度分别设为len m和n,因此返回值为dp[len][m][n]
代码如下:

public int findMaxForm(String[] strs, int m, int n) {
        int len = strs.length;
        int[][][] dp = new int[len + 1][m + 1][n + 1];

        for (int i = 1; i <= len; i++) {
            int count0 = 0;
            int count1 = 0;
            for (char ch : strs[i - 1].toCharArray()) {
                if (ch == '0') {
                    count0++;
                } else {
                    count1++;
                }
            }
            for (int j = 0; j <= m; j++) {
                for (int k = 0; k <= n; k++) {
                    dp[i][j][k] = dp[i - 1][j][k];
                    if (j - count0 >= 0 && k - count1 >= 0) {
                        dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j - count0][k - count1] + 1);
                    }
                }
            }

        }
        return dp[len][m][n];

    }

代码运行效率:
在这里插入图片描述
优化后代码如下:
这里优化要注意一个问题,这题近似于一个01背包问题,所以jk两个维度下标都需要从大到小进行运算。

public int findMaxForm(String[] strs, int m, int n) {
        int len = strs.length;
        int[][] dp = new int[m + 1][n + 1];

        for (int i = 1; i <= len; i++) {
            int count0 = 0;
            int count1 = 0;
            for (char ch : strs[i - 1].toCharArray()) {
                if (ch == '0') {
                    count0++;
                } else {
                    count1++;
                }
            }
            for (int j = m; j >= count0; j--) {
                for (int k = n; k >= count1; k--) {

                    dp[j][k] = Math.max(dp[j][k], dp[j - count0][k - count1] + 1);

                }
            }

        }
        return dp[m][n];

    }

优化后运行效率:
在这里插入图片描述
题目链接
时间复杂度:O(N^3)
空间复杂度:O(N^3)
优化后空间复杂度:O(N^2)

2. 盈利计划(879)

题目描述:
在这里插入图片描述

状态表示:
和上一题类似,这题也是多加了一个限制条件的01背包问题,所以建立三维数组dp,使用dp[i][j][k]来表示在前i个计划中选择,要求人员数不大于j并且利润不低于k时的满足条件的最多选法。
状态转移方程:
状态分析也是和01背包问题是类似的,就是对第i个计划的选择来进行分析,当不选该计划时dp[i][j][k]=dp[i-1][j][k].当选择该计划时并且满足j>=group[i]时,dp[i][j][k]=dp[i][j-group[i]][max(0,k-profit[i])],这里解释一下第三个维度,因为第三个维度就是要求利润要不少于k,所以k-profit[i]即使小于0也没有关系。因为此时可以得到不等式k<profit[i],我们状态表示是计划加起来的利润要大于等于k,此时光加入profit[i]都已经大于k了,我们自然希望加起来的利润越大越好,但是因为数组中的下标值不能为0,所以如果纬度值小于0直接取0即可。
初始化:
为了避免数组越界问题以及方便初始化,对dp数组的三个维度都加上一行/列,对于j和k这两个维度因为这题实际上也是一个01背包问题,所以直接不初始化加入运算即可。当i维度等于0时,也就是i等于0时的那个平面,因为此时没有计划,所以没有利润以及人员的需求,此时当无论j取多少这个条件都是满足的,但是因为利润至少为k,所以只有当k==0时会有一种选法。综上对dp[0][j][0]这一列/行全赋为1,其余初始化为0即可。
填表顺序:
对于i要从小到大进行运算,j和k下标顺序随意。
返回值:
初始化三维数组时形式如dp[len+1][n+1][minProfit+1],所以返回dp[len][n][minProfit]即可。
代码如下:

class Solution {
    public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
        int len = group.length;
        int TEMP = (int) 1e9 + 7;
        int[][][] dp = new int[len + 1][n + 1][minProfit + 1];
        for (int i = 0; i <= n; i++) {
            dp[0][i][0] = 1;
        }

        for (int i = 1; i <= len; i++) {
            for (int j = 0; j <= n; j++) {
                for (int k = 0; k <= minProfit; k++) {
                    dp[i][j][k] = dp[i - 1][j][k];
                    if (j >= group[i - 1]) {
                        dp[i][j][k] += dp[i - 1][j - group[i - 1]][Math.max(0, k - profit[i - 1])];
                        dp[i][j][k] %= TEMP;
                    }
                }
            }
        }
        return dp[len][n][minProfit];
    }
}

代码运行效率:
在这里插入图片描述

优化后代码如下:

class Solution {
    public int profitableSchemes(int n, int minProfit, int[] group, int[] profit) {
        int len = group.length;
        int TEMP = (int) 1e9 + 7;
        int[][] dp = new int[n + 1][minProfit + 1];
        for (int i = 0; i <= n; i++) {
            dp[i][0] = 1;
        }

        for (int i = 1; i <= len; i++) {
            for (int j = n; j >= group[i - 1]; j--) {
                for (int k = minProfit; k >= 0; k--) {

                    dp[j][k] += dp[j - group[i - 1]][Math.max(0, k - profit[i - 1])];
                    dp[j][k] %= TEMP;

                }
            }
        }
        return dp[n][minProfit];
    }
}

优化后运行效率:
在这里插入图片描述

题目链接
时间复杂度:O(N^3)
空间复杂度:O(N^3)
优化后空间复杂度:O(N^2)

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

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

相关文章

IT技术 | 电脑蓝屏修复记录DRIVER_IRQL_NOT_LESS_OR_EQUAL

我的台式机是iMac 2015年的&#xff0c;硬盘是机械的&#xff0c;时间久了运行越来越慢。后来对苹果系统失去了兴趣&#xff0c;想换回windows&#xff0c;且想换固态硬盘&#xff0c;就使用winToGo 搞了双系统&#xff0c;在USB外接移动固态硬盘上安装了win10系统。 最近&…

安卓六种页面加载优化方案对比总结

根据工作经验&#xff0c;笔者提炼了六种页面加载优化方式&#xff0c;按照业务与非业务&#xff0c;将六种加载方式分为两类&#xff1a; 业务类 控制业务与UI的执行顺序、控制多业务之间的执行顺序 ①预加载&#xff1a;是指在进入页面之前&#xff0c;提前获得页面所需得数据…

2024经济管理、社会科学与教育国际会议(ICEMSSE 2024)

2024经济管理、社会科学与教育国际会议(ICEMSSE 2024) 会议简介 2024年国际经济管理、社会科学和教育会议&#xff08;ICEMSSE 2024&#xff09;专注于经济、社会发展和教育。会议旨在为专家、学者和社会人士提供一个交流平台。通过讨论科学研究成果和前沿技术&#xff0c;我…

浅谈配置元件之CSV 数据文件设置

浅谈配置元件之CSV 数据文件设置 为了增强测试的真实性和多样性&#xff0c;JMeter 提供了多种数据参数化的方式&#xff0c;其中 CSV 数据文件设置&#xff08;CSV Data Set Config&#xff09;是一种常用且强大的功能&#xff0c;它允许测试脚本从外部CSV文件中动态读取数据…

基于springboot+vue的“漫画之家”系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

Samtec mPower®电源连接器:高能、可靠、灵活、小巧

【摘要/前言】 电源连接器是互连解决方案中不可或缺的一个组成部分。虽然相较于比较爱“竞速”的信号连接器&#xff0c;电源连接器的技术迭代不是那么频繁&#xff0c;但是它是连接电源和用电设备的重要纽带&#xff0c;想要确保设备正常运行&#xff0c;就少不了它的身影。 …

EPSON RX8111CE+松下高性能电池的组合应用

RTC是一种实时时钟&#xff0c;用于记录和跟踪时间&#xff0c;具有独立供电和时钟功能。在某些应用场景中&#xff0c;为了保证RTC在断电或者其他异常情况下依然能够正常工作&#xff0c;需要备份电池方案来提供稳定的供电。本文将介绍EPSON爱普生nA级RTC RX8111CE松下Panason…

ESP32-C6构建Matter Wi-Fi和Thread终端设备的利器,启明云端乐鑫代理商

随着物联网技术的飞速发展&#xff0c;越来越多的智能设备开始融入我们的日常生活。在智能家居和智能家电领域&#xff0c;ESP32系列产品以其高性能的微控制器&#xff08;MCU&#xff09;和无线通信解决方案而深入人心。 作为乐鑫代理商&#xff0c;启明云端为广大开发者提供…

Python代码:十八、生成数字列表

1、描述 牛牛在牛客网系统录入了一连串数字&#xff0c;数字之间依靠逗号隔开&#xff0c;你能帮助他将这些数字存储在列表中吗&#xff0c;列表元素以int的形式。 输入描述&#xff1a; 输入一行整数&#xff0c;数字之间以空格间隔。 输出描述&#xff1a; 输出这些数字…

【5G NB-IoT NTN】基于IoT NTN实现卫星语音通信的关键技术研究

近年来&#xff0c;随着商业航天的兴起&#xff0c;卫星制造和发射成本大幅降低&#xff0c;星载天线技术快速发展&#xff0c;为卫星通信产业注入了新的活力。同时&#xff0c;随着通信芯片、终端能力的提升&#xff0c;基于星地网络融合的公众手持终端直连卫星逐步成为现实。…

超融合架构下,虚拟机高可用机制如何构建?

作者&#xff1a;SmartX 产品部 钟锦锌 虚拟机高可用&#xff08;High Availability&#xff0c;简称 HA&#xff09;是虚拟化/超融合平台最常用、关键的功能之一&#xff0c;可在服务器发生故障时通过重建业务虚拟机以降低故障对业务带来的影响。因此&#xff0c;为了充分保障…

什么是驾驶舱?这3种驾驶舱领导最爱看

在当今快速变化的商业环境中&#xff0c;企业决策者需要实时、准确地掌握企业运营的各个方面&#xff0c;以便迅速做出明智的决策。数据驾驶舱&#xff0c;作为一种先进的管理工具&#xff0c;正逐渐成为企业管理层的必备利器。本文将深入探讨数据驾驶舱的概念、类型、角色多维…

DAOS: A Scale-Out High Performance Storage Stack for Storage Class Memory——论文泛读

Supercomputing Frontiers 2020 Paper 分布式元数据论文阅读笔记整理 问题 企业、政府和学术界出现的数据密集型应用程序将现有的I/O模型扩展到了极限。现代I/O工作负载的特点是元数据与未对齐和碎片化数据的结合比例越来越高。传统的存储堆栈为这些工作负载提供了较差的性能…

从原理上解决 uniapp (含第三方插件)打包 iOS APP 失败的问题

最近一段时间&#xff0c;我的团队基于uniapp开发的平台型APP因平台资金合规的要求&#xff0c;需要对接中金支付&#xff0c;uniapp的插件市场有一个别人做好的中金支付插件&#xff0c;但前端开发同事在引用这个 插件时&#xff0c;出现了 iOS APP 打包不成功的情况&#xff…

通付盾Web3专题 | SharkTeam:Web3常见钓鱼方式分析与安全防范建议

引言 Web3钓鱼是一种针对Web3用户的常见攻击手段&#xff0c;通过各种方式窃取用户的授权、签名&#xff0c;或诱导用户进行误操作&#xff0c;目的是盗窃用户钱包中的加密资产。 近年来&#xff0c;Web3钓鱼事件不断出现&#xff0c;且发展出钓鱼即服务的黑色产业链&#xf…

python+pymysql对数据库进行增、删、改、查操作

一、概述 接口测试中&#xff0c;应用到数据库操作的场景&#xff1a; 1.校验测试数据 接口发送请求后明确会对数据库中的某个字段进行修改&#xff08;编辑&#xff0c;更新、删除操作&#xff09;&#xff0c;但&#xff0c;响应结果中无该字段数据时。 例如&#xff1a;删…

QML-1- qml简介及项目创建

文章目录 1. QML 简介2. 项目创建3. 目录结构4. CMakeLists.txt 简单介绍5. 运行demo 1. QML 简介 根据官网介绍&#xff0c;qml 为qt一个模块&#xff0c;使用Qml语言开发应用程序和库提供了一个框架。它定义并实现了语言和引擎基础结构&#xff0c;并提供了一个API&#xff…

搭建属于自己的 Git 仓库:GitLab

搭建属于自己的 Git 仓库&#xff1a;使用 GitLab 文章目录 搭建属于自己的 Git 仓库&#xff1a;使用 GitLab什么是 GitLab&#xff1f;准备工作安装 Docker使用Docker Compose 快速构建GitLab1、从docker compose快速搭建GitLab2、部署到服务器并访问3、浏览器访问 在现代软件…

Linux-挂盘-分区-卸盘

Linux-挂盘-分区-卸盘 1. 添加硬盘 2. 查看硬盘 [rootlocalhost /]# lsblk # 查看我们新添加的磁盘 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 80G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 …