【算法挨揍日记】day45——474. 一和零、879. 盈利计划

 474. 一和零

474. 一和零

题目描述:

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

 解题思路:

算法思路:
先将问题转化成我们熟悉的题型。
i. 在⼀些物品中「挑选」⼀些出来,然后在满⾜某个「限定条件」下,解决⼀些问题,⼤概率
是背包模型;
ii. 由于每⼀个物品都只有 1 个,因此是⼀个「01 背包问题」。
但是,我们发现这⼀道题⾥⾯有「两个限制条件」。因此是⼀个「⼆维费⽤的 01 背包问题」。那
么我们定义状态表⽰的时候,来⼀个三维 dp 表,把第⼆个限制条件加上即可。
1. 状态表⽰:
dp[i][j][k] 表⽰:从前 i 个字符串中挑选,字符 0 的个数不超过 j ,字符 1 的个数不
超过 k ,所有的选法中,最⼤的⻓度。
2. 状态转移⽅程:
线性 dp 状态转移⽅程分析⽅式,⼀般都是「根据最后⼀步」的状况,来分情况讨论。为了⽅便
叙述,我们记第 i 个字符中,字符 0 的个数为 a ,字符 1 的个数为 b
i. 不选第 i 个字符串:相当于就是去前 i - 1 个字符串中挑选,并且字符 0 的个数不超
j ,字符 1 的个数不超过 k 。此时的最⼤⻓度为 dp[i][j][k] = dp[i - 1]
[j][k]
ii. 选择第 i 个字符串:那么接下来我仅需在前 i - 1 个字符串⾥⾯,挑选出来字符 0
个数不超过 j - a ,字符 1 的个数不超过 k - b 的最⻓⻓度,然后在这个⻓度后⾯加
上字符串 i 即可。。此时 dp[i][j][k] = dp[i - 1][j - a][k - b] + 1
但是这种状态不⼀定存在,因此需要特判⼀下。
综上,状态转移⽅程为: dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - a]
[k - b] + 1)
3. 初始化:
当没有字符串的时候,没有⻓度,因此初始化为 0 即可。
4. 填表顺序:
保证第⼀维的循环「从⼩到⼤」即可。
5. 返回值:
根据「状态表⽰」,我们返回 dp[len][m][n]
其中 len 表⽰字符串数组的⻓度。
6. 空间优化:
所有的「背包问题」,都可以进⾏空间上的优化。
对于「⼆维费⽤的 01 背包」类型的,我们的优化策略是:
i. 删掉第⼀维;
ii. 修改第⼆层以及第三层循环的遍历顺序即可

解题代码:

class Solution {
public:
    int f(string s,char ch)
    {
        int ret=0;
        for(int i=0;i<=s.size();i++)
            if(s[i]==ch)    ret++;
        return ret;
    }
    int findMaxForm(vector<string>& strs, int m, int n) {
        int len=strs.size();
        vector<vector<vector<int>>>dp(len+1,vector<vector<int>>(m+1,vector<int>(n+1)));
        for(int i=1;i<=len;i++)
        {
            for(int j=0;j<=m;j++)
            {
                for(int k=0;k<=n;k++)
                {
                    dp[i][j][k]=dp[i-1][j][k];
                    int a=f(strs[i-1],'0');//0的个数
                    int b=f(strs[i-1],'1');//1的个数
                    if(j>=a&&k>=b)
                    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a][k-b]+1);
                }
            }
        }
        return dp[len][m][n];
    }
};

 879. 盈利计划

879. 盈利计划

题目描述:

集团里有 n 名员工,他们可以完成各种各样的工作创造利润。

第 i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。

工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n 。

有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值

 

解题思路:

算法思路:
这道题⽬⾮常难读懂,但是如果结合例⼦多读⼏遍,你就会发现是⼀个经典的「⼆维费⽤的背包问
题」。因此我们可以仿照「⼆维费⽤的背包」来定义状态表⽰。
1. 状态表⽰:
dp[i][j][k] 表⽰:从前 i 个计划中挑选,总⼈数不超过 j ,总利润⾄少为 k ,⼀共有多
少种选法。
注意注意注意,这道题⾥⾯出现了⼀个「⾄少」,和我们之前做过的背包问题不⼀样。因此,我们
在分析「状态转移⽅程」的时候要结合实际情况考虑⼀下。
2. 状态转移⽅程:
⽼规矩,根据「最后⼀个位置」的元素,结合题⽬的要求,我们有「选择」最后⼀个元素或者「不
选择」最后⼀个元素两种策略:
i. 不选 i 位置的计划:那我们只能去前 i - 1 个计划中挑选,总⼈数不超过 j ,总利润
⾄少为 k 。此时⼀共有 dp[i - 1][j][k] 种选法;
ii. 选择 i 位置的计划:那我们在前 i - 1 个计划中挑选的时候,限制就变成了,总⼈数不
超过 j - g[i] ,总利润⾄少为 k - p[i] 。此时⼀共有 dp[i - 1][j - g[i]]
[k - p[i]]
第⼆种情况下有两个细节需要注意:
1. j - g[i] < 0 :此时说明 g[i] 过⼤,也就是⼈数过多。因为我们的状态表⽰要
求⼈数是不能超过 j 的,因此这个状态是不合法的,需要舍去。
2. k - p[i] < 0 :此时说明 p[i] 过⼤,也就是利润太⾼。但是利润⾼,不正是我
们想要的嘛?所以这个状态「不能舍去」。但是问题来了,我们的 dp 表是没有负数的
下标的,这就意味着这些状态我们⽆法表⽰。其实,根本不需要负的下标,我们根据实
际情况来看,如果这个任务的利润已经能够达标了,我们仅需在之前的任务中,挑选出
来的利润⾄少为 0 就可以了。因为实际情况不允许我们是负利润,那么负利润就等价
于利润⾄少为 0 的情况。所以说这种情况就等价于 dp[i][j][0] ,我们可以对 k
- p[i] 的结果与 0 取⼀个 max
综上,我们的状态转移⽅程为:
dp[i][j][k] = dp[i - 1][j][k] + dp[i - 1][j - g[i - 1]][max(0, k
- p[i - 1])]
3. 初始化:
当没有任务的时候,我们的利润为 0 ,此时⽆论⼈数限制为多少,我们都能找到⼀个「空集」的
⽅案。
因此初始化 dp[0][j][0] 的位置为 1 ,其中 0 <= j <= n
4. 填表顺序:
根据「状态转移⽅程」,我们保证 i 从⼩到⼤即可。
5. 返回值:
根据「状态表⽰」,我们返回 dp[len][m][n]
其中 len 表⽰字符串数组的⻓度。
6. 空间优化:
所有的「背包问题」,都可以进⾏空间上的优化。
对于「⼆维费⽤的 01 背包」类型的,我们的优化策略是:
i. 删掉第⼀维;
ii. 修改第⼆层以及第三层循环的遍历顺序即可。

解题代码:

class Solution {
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        const int MOD=1e9+7;
        int len=group.size();
        vector<vector<vector<int>>>dp(len+1,vector<vector<int>>(n+1,vector<int>(minProfit+1)));
        for(int j=0;j<=n;j++)   dp[0][j][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]][max(k-profit[i-1],0)];
                    dp[i][j][k]%=MOD;
                }
            }
        }
        return dp[len][n][minProfit];
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发入门

一、开发准备 1.1 开发环境搭建 鸿蒙开发文档华为账号注册DevEco Studio 下载 二、快速入门 三、ArkUI 3.1 Image 3.2 Text 3.3 TextInput 3.4 Button 3.5 循环控制 3.6 List 3.7 自定义 3.8 状态管理 3.8.1 State 装饰器 3.8.2 Prop、Link 装饰器 // 父组件 State str: …

【每日论文阅读】生成模型篇

联邦多视图合成用于元宇宙 标题: Federated Multi-View Synthesizing for Metaverse 作者: Yiyu Guo; Zhijin Qin; Xiaoming Tao; Geoffrey Ye Li 摘要: 元宇宙有望提供沉浸式娱乐、教育和商务应用。然而&#xff0c;虚拟现实&#xff08;VR&#xff09;在无线网络上的传输是…

【Java】SpringBoot整合xxl-job学习使用详解

文章目录 介绍作用如何使用下载项目中央仓库地址环境调度中心初始化“调度数据库”配置部署“调度中心”部署项目调度中心集群&#xff08;可选&#xff09;其他&#xff1a;Docker 镜像方式搭建调度中心配置部署“执行器项目” 执行器maven依赖执行器配置执行器组件配置执行器…

人工智能_机器学习088_DBSCAN聚类案例_KMeans聚类算法效果展示---人工智能工作笔记0128

然后我们先来看一下上一节的代码首先导包 import numpy as np 导入数学计算包 import matplotlib.pyplot as plt 导入画图包 from sklearn.cluster import KMeans,DBSCAN 导入算法 from sklearn import datasets 导入数据集包 然后我们再去创建数据 X,y = datasets.make_c…

MyBatis学习一:快速入门

前言 公司要求没办法&#xff0c;前端也要了解一下后端知识&#xff0c;这里记录一下自己的学习 学习教程&#xff1a;黑马mybatis教程全套视频教程&#xff0c;2天Mybatis框架从入门到精通 文档&#xff1a; https://mybatis.net.cn/index.html MyBatis 快速入门&#xf…

纠删码ReedSolomon

随着大数据技术的发展&#xff0c;HDFS作为Hadoop的核心模块之一得到了广泛的应用。为了数据的可靠性&#xff0c;HDFS通过多副本机制来保证。在HDFS中的每一份数据都有两个副本&#xff0c;1TB的原始数据需要占用3TB的磁盘空间&#xff0c;存储利用率只有1/3。而且系统中大部分…

初识Linux下进程

&#x1f30e;初识进程 初识进程 简单认识一下进程 如何管理进程 进程属性信息 内核运行队列 查看进程 通过系统调用获取进程标识符       父子进程       查看运行中的进程 总结 前言&#xff1a; 我们在电脑上点开的一个个应用&#xff0c;其实就是一个个进程&am…

【输入npm install express出现的报错】

目录 输入&#xff1a;npm install express&#xff0c;出现如下的报错 分析原因 方法1&#xff1a;用管理员的身份进行安装 方法2&#xff1a;更改文件夹的权限 输入&#xff1a;npm install express&#xff0c;出现如下的报错 分析原因&#xff1a; npm在执行安装过程中…

HTML5和JS实现明媚月色效果

HTML5和JS实现明媚月色效果 先给出效果图&#xff1a; 源码如下&#xff1a; <!DOCTYPE html> <html> <head><title>明媚月光效果</title><style>body {margin: 0;overflow: hidden;background-color: #000; /* 添加一个深色背景以便看到…

vscode中增加参数的一个方法

1 在settings.json 文件中增加参数 2. 在参数中配置 这里也是ok的

VMware 虚拟机 ubuntu 20.04 硬盘扩容方法

前言 最近由于需要编译 【RK3568】的 Linux SDK&#xff0c;发现 虚拟机默认的 200G 空间不足了&#xff0c;因此想增加这个 200G 空间的限制&#xff0c;通过网络上查找了一些方法&#xff0c;加上自己亲自验证&#xff0c;确认 硬盘扩容 正常&#xff0c;方法也比较的容易&a…

MySQL--安装与配置与向日葵的基本操作使用

一.MySQL介绍 1.1 MySQL简介 MySQL是一个开源的关系型数据库管理系统&#xff0c;最早由瑞典MySQL AB公司开发。这个数据库系统有着高可靠性、高性能和易用性的特点&#xff0c;在互联网上得到了广泛的应用。MySQL支持SQL语言&#xff0c;可以运行在多种操作系统上&#xff0c…

draw流程图工具导入云原生(CNCF)相关控件

目录 1、通过draw导入xml文件&#xff0c;获取云原生相关的空间 2、引用自己的资源链接&#xff1a; 1、通过draw导入xml文件&#xff0c;获取云原生相关的空间 导入资源图库&#xff0c;资源放在下方&#xff0c;大家可以下载&#xff1a; 2、引用自己的资源链接&#xff1a;…

C#中汉字转区位码

目录 一、关于区位码 1.区位码定义 2.算法 二、实例 三、生成效果 四、程序中的知识点 1.byte[] GetBytes(string s) 2.字节数组转short类型 一、关于区位码 1.区位码定义 区位码是一个4位的十进制数&#xff0c;每个区位码都对应着一个唯一的汉字&#xff0c;区位码…

小白综述:深度学习 OCR 图片文字识别

文章目录 1. OCR 算法流程1.1 传统 OCR 方法1.2 深度学习 OCR 方法1.2.1 two-stage方法&#xff1a;文字检测识别1.2.2 端到端方法 2. 文本检测算法3. 文本识别算法3.1 基于分割的单字符识别方法3.2 基于序列标注的文本行识别方法 1. OCR 算法流程 OCR (Optical Character Rec…

opencv期末练习题(3)附带解析

创建黑色画板&#xff0c;并支持两种画图功能 import mathimport cv2 import numpy as np """ 1. 创建一个黑色画板 2. 输入q退出 3. 输入m切换画图模式两种模式&#xff0c;画矩形和画圆形。用户按住鼠标左键到一个位置然后释放就可以画出对应的图像 "&qu…

Blender:从新手到专家的全方位指南

Blender&#xff0c;这款强大的开源3D建模和渲染软件&#xff0c;已经成为了CG行业的标准工具之一。它不仅拥有丰富的教程资源&#xff0c;而且还在不断发展和完善中。尽管Blender的教程主要集中在国外网站和YouTube上&#xff0c;但其全面的功能和易用性使它成为许多人的首选工…

基于深度卷积神经网络的猴痘分类识别系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细介绍了一基于深度卷积神经网络的猴痘分类识别系统。采用TensorFlow和Keras框架&#xff0c;通过卷积神经网络&#xff08;CNN&#xff09;进行模型训练和预测&#xff0c;利用迁移学习中的…

【ESP-NOW Web 服务器传感器仪表板 (ESP-NOW + Wi-Fi)】

【ESP-NOW Web 服务器传感器仪表板 &#xff08;ESP-NOW Wi-Fi&#xff09;】 1. 前言2. 同时使用 ESP-NOW 和 Wi-Fi3. 项目概况4. 先决条件4.1 环境配置4.2 DHT 库4.3 ESPAsyncWebSrv服务器库4.4 Arduino_JSON4.5 所需零件4.6 获取接收板 MAC 地址4.7 ESP32 发送电路 5. ESP3…