[Algorithm][动态规划][二维费用的背包问题][一和零][盈利计划]详细讲解

本文主要是介绍[Algorithm][动态规划][二维费用的背包问题][一和零][盈利计划]详细讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 0.原理讲解
  • 1.一和零
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.盈利计划
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


0.原理讲解

  • 本质仍然是背包问题,但是相较于普通的背包问题,只是限制条件多了一个而已

1.一和零

1.题目链接

  • 一和零

2.算法原理详解

  • 思路
    • 确定状态表示 -> dp[i][j]的含义

      • dp[i][j][k]:从前i个字符串中挑选,字符0的个数不超过j,字符1的个数不超过k,所有的选法中,最大的长度
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论
      请添加图片描述

    • 初始化:

      • 三个维度都多开一“行”虚拟结点
      • j, k这两个维度的初始化都可以交给DP阶段
    • 确定填表顺序:i从小到大

    • 确定返回值:dp[len][n][m]

  • 滚动数组优化空间
    • 大致思路与完全背包一致
    • 操作
      • 删除所有的i
      • 修改一下j, k的遍历顺序
    • 注意不要去强行解释优化后的妆台表示以及状态转移方程,费时费力还没啥意义

3.代码实现

// v1.0
int findMaxForm(vector<string>& strs, int n, int m) 
{int len = strs.size();vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(n + 1, vector<int>(m + 1)));for(int i = 1; i <= len; i++){// 先统计字符串中0 1的个数int a = 0, b = 0;for(auto& ch : strs[i - 1]){ch == '0' ? a++ : b++;}// DPfor(int j = 0; j <= n; j++){for(int k = 0; k <= m; k++){dp[i][j][k] = dp[i - 1][j][k];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][n][m];
}
---------------------------------------------------------------------------------
// v2.0 滚动数组优化
int findMaxForm(vector<string>& strs, int n, int m) 
{int len = strs.size();vector<vector<int>> dp(n + 1, vector<int>(m + 1));for(int i = 1; i <= len; i++){// 先统计字符串中0 1的个数int a = 0, b = 0;for(auto& ch : strs[i - 1]){ch == '0' ? a++ : b++;}// DPfor(int j = n; j >= a; j--){for(int k = m; k >= b; k--){dp[j][k] = max(dp[j][k], dp[j - a][k - b] + 1);}}}return dp[n][m];
}

2.盈利计划

1.题目链接

  • 盈利计划

2.算法原理详解

  • 思路
    • 确定状态表示 -> dp[i][j]的含义

      • dp[i][j][k]:从前i个计划中挑选,总人数不超过j,总利润至少为k,一共有多少种选法
    • 推导状态转移方程:根据最后一个位置的情况,分情况讨论
      请添加图片描述

    • 初始化:

      • 三个维度都多开一“行”虚拟结点
      • dp[0][j][0] = 1
      • k这个维度的初始化可以交给DP阶段
    • 确定填表顺序:i从小到大

    • 确定返回值:dp[len][n][m]

  • 滚动数组优化空间
    • 大致思路与完全背包一致
    • 操作
      • 删除所有的i
      • 修改一下j, k的遍历顺序
    • 注意不要去强行解释优化后的妆台表示以及状态转移方程,费时费力还没啥意义

3.代码实现

// v1.0
int profitableSchemes(int n, int m, vector<int>& g, vector<int>& p) 
{const int MOD = 1e9 + 7;int len = g.size();// Initvector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(n + 1, vector<int>(m + 1)));for(int j = 0; j <= n; j++){dp[0][j][0] = 1;}// DPfor(int i = 1; i <= len; i++){for(int j = 0; j <= n; j++){for(int k = 0; k <= m; k++){dp[i][j][k] = dp[i - 1][j][k];if(j >= g[i - 1]){dp[i][j][k] += dp[i - 1][j - g[i - 1]][max(0, k - p[i - 1])];}dp[i][j][k] %= MOD;}}}return dp[len][n][m];
}
------------------------------------------------------------------------------
// v2.0 滚动数组优化
int profitableSchemes(int n, int m, vector<int>& g, vector<int>& p) 
{const int MOD = 1e9 + 7;int len = g.size();// Initvector<vector<int>> dp(n + 1, vector<int>(m + 1));for(int j = 0; j <= n; j++){dp[j][0] = 1;}// DPfor(int i = 1; i <= len; i++){for(int j = n; j >= g[i - 1]; j--){for(int k = m; k >= 0; k--){dp[j][k] += dp[j - g[i - 1]][max(0, k - p[i - 1])];dp[j][k] %= MOD;}}}return dp[n][m];
}

这篇关于[Algorithm][动态规划][二维费用的背包问题][一和零][盈利计划]详细讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

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

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

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

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