NO.88十六届蓝桥杯备战|动态规划-多重背包|摆花(C++)

多重背包

多重背包问题有两种解法:

  1. 按照背包问题的常规分析⽅式,仿照完全背包,第三维枚举使⽤的个数;
  2. 利⽤⼆进制可以表⽰⼀定范围内整数的性质,转化成01 背包问题。
    ⼩建议:并不是所有的多重背包问题都能⽤⼆进制优化,⽽且优化版本的代码很⻓。因此,如果时间复杂度允许的情况下,能不优化就不优化
    解法⼀:常规分析
  3. 状态表⽰:
    dp[i][j]表⽰:从前i 个物品中挑选,总重量不超过j 的情况下,最⼤的价值。
    dp[n][m]就是最终结果。
  4. 状态转移⽅程:
    根据第i 个物品选的个数,可以分x[i] + 1种情况:
    a. 选0 个:价值为dp[i - 1][j]
    b. 选1 个:价值为dp[i - 1][j - w[i]] + v[i]
    c. 选2 个:价值为dp[i - 1][j - 2 × w[i]] + 2 × v[i]
    d. …
    e. 选x[i]个:价值为dp[i - 1][j - x[i] × w[i]] + x[i] × v[i]
    因为要的是最⼤价值,所以dp[i][j]等于上述所有情况的最⼤值。但是要注意j-k*w[i]要⼤于等于0,并且不能按照完全背包的⽅式优化。
  5. 初始化:
    全部为0 就不影响最终结果
  6. 填表顺序:
    从上往下每⼀⾏,每⼀⾏从左往右
#include <bits/stdc++.h>
using namespace std;const int N = 110;int n, m;
int x[N], w[N], v[N];
int f[N][N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> x[i] >> w[i] >> v[i];for (int i = 1; i <= n; i++)for (int j = m; j >= 0; j--)for (int k = 0; k <= x[i] && k * w[i] <= j; k++){f[i][j] = max(f[i][j], f[i-1][j - k*w[i]] + k * v[i]);}cout << f[n][m] << endl;return 0;
}

空间优化:

#include <bits/stdc++.h>
using namespace std;const int N = 110;int n, m;
int x[N], w[N], v[N];
int f[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> x[i] >> w[i] >> v[i];for (int i = 1; i <= n; i++)for (int j = m; j >= 0; j--)for (int k = 0; k <= x[i] && k * w[i] <= j; k++){f[j] = max(f[j], f[j - k*w[i]] + k * v[i]);}cout << f[m] << endl;return 0;
}

解法⼆:转化成01背包问题
优化⽅式:⽤⼆进制将x[i]个物品分组。
连续的⼆进制数有⼀个性质,就是 2 0 ∼ 2 k 2^{0}\sim 2^k 202k能够表⽰区间[1, 2^(k+1) - 1]⾥⾯所有的整数。⽐如:

  • 1, 2, 4, 8可以表⽰[1, 15]内所有的整数。具体原因可以参考整数的⼆进制表⽰,正好1, 2, 4, 8对应⼆进制表⽰中每⼀位的权值,所以排列组合起来就可以表⽰[1,15]内所有的整数。
  • 同理1, 2, 4 就可以表⽰[1, 7]内所有的整数。
    根据这样⼀个性质,我们就可以把x[i]拆成⼀些⼆进制数再加上多出来的数,这样的⼀组数就可以表⽰[1,x[i]]内所有的整数,问题就变成了01背包
    ⽐如x[i] = 9,w[i] = 2, v[i] = 3
  • 9 = 1 + 2 + 4 + 2 ;
  • 分成4 组,每组的重量和价值分别为(2, 3)、(4, 6)、(8, 12)、(4, 6)
#include <bits/stdc++.h>
using namespace std;const int N = 110 * 5;int n, m;
int w[N], v[N], pos;
int f[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++){int x, y, z; cin >> x >> y >> z;//2进制拆分int t = 1;while (x >= t){pos++;w[pos] = t * y;v[pos] = t * z;x -= t;t *= 2;}if (x) //处理剩余{pos++;w[pos] = x * y;v[pos] = x * z;}}//01背包for (int i = 1; i <= pos; i++)for (int j = m; j >= w[i]; j--)f[j] = max(f[j], f[j - w[i]] + v[i]);cout << f[m] << endl;return 0;
}
P1077 [NOIP 2012 普及组] 摆花 - 洛谷

题意:每⼀种花可以选[0, a[i]]个,在总数恰好等于m 时的总⽅案数
正好是多重背包求⽅案数的模型,我们可以⽤多重背包的思考⽅式来解决这道题。

  1. 状态表⽰:
    dp[i][j]表⽰:从前i个花中挑选,正好摆放j 个花盆时的⽅案数。
  2. 状态转移⽅程:
    根据第i 种花选的个数k(0 ≤ k ≤ min(j, a[i])) 分情况讨论:
  • 如果当前花选了k 盆,之前的花要去凑够j - k 盆,总的⽅案数就是dp[i - 1][j - k]
  • 因为要的是总⽅案数,所以最终结果应该是k 的变化过程中的状态的总和。
    dp[i][j] = dp[i][j] + dp[i - 1][j - k]
  1. 初始化:
    dp[0][0] = 1 ,相当于起始状态,为了让后续的填表有意义,不然全都是0 。
  2. 填表顺序:
    从上往下每⼀⾏,每⼀⾏从左往右。
    这道题就不能⽤⼆进制优化,因为这道题的背包,限定条件和价值是⼀⼀对应的,并且求的是⽅案数。如果⽤⼆进制优化会统计多余的情况,⽐如:
  • 有两个物品,个数分别是3, 2 ,要凑成总和为4 。
  • 拆分之后为(1, 2)、(1, 1) ,跑⼀遍01 背包之后,结果是 3 ,但是实际情况应该是2 。
  • 原因是1,2,1被统计了2次。但是在实际情况⾥,第⼀个物品全选,第⼆个物品选1个,只属于1种情况,⽽01背包的逻辑会统计两次
#include <bits/stdc++.h>
using namespace std;const int N = 110, MOD = 1e6 + 7;int n, m;
int a[N];
int f[N][N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> a[i];f[0][0] = 1;for (int i = 1; i <= n; i++){for (int j = m; j >= 0; j--){for (int k = 0; k <= j && k <= a[i]; k++){f[i][j] = (f[i][j] + f[i-1][j-k]) % MOD;        }}}cout << f[n][m] << endl;return 0;
}

空间优化

#include <bits/stdc++.h>
using namespace std;const int N = 110, MOD = 1e6 + 7;int n, m;
int a[N];
int f[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> a[i];f[0] = 1;for (int i = 1; i <= n; i++){for (int j = m; j >= 0; j--){for (int k = 1; k <= j && k <= a[i]; k++){f[j] = (f[j] + f[j-k]) % MOD;        }}}cout << f[m] << endl;return 0;
}

单独考虑k==0

#include <bits/stdc++.h>
using namespace std;const int N = 110, MOD = 1e6 + 7;int n, m;
int a[N];
int f[N][N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> a[i];f[0][0] = 1;for (int i = 1; i <= n; i++){for (int j = m; j >= 0; j--){f[i][j] = f[i-1][j];for (int k = 1; k <= j && k <= a[i]; k++){f[i][j] = (f[i][j] + f[i-1][j-k]) % MOD;        }}}cout << f[n][m] << endl;return 0;
}

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

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

相关文章

【远程工具】0 std::process::Command 介绍

std::process::Command 是 Rust 标准库中用于创建和配置子进程的主要类型。它允许你启动新的进程、设置其参数和环境变量、重定向输入/输出等。 基本用法 use std::process::Command;let output Command::new("echo").arg("Hello, world!").output().ex…

【图书管理系统】深入解析基于 MyBatis 数据持久化操作:全栈开发图书管理系统获取图书列表接口(后端:计算图书页数、查询当前页展示的书籍)

图书列表 实现服务器代码(计算图书总数量查询当前页需要展示的书籍) 后端响应时&#xff0c;需要响应给前端的数据 records&#xff1a;第 pageNum 页要展示的图书有哪些&#xff08;存储到List集合中&#xff09;total&#xff1a;计算一共有多少本书&#xff08;用于告诉前…

如何在idea中快速搭建一个Spring Boot项目?

文章目录 前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热启动&#xff08;热部署&#xff09;结语 前言 Spring Boot 凭借其便捷的开发特性&#xff0c;极大提升了开发效率&#xff0c;为 Java 开发工作带来诸多便利。许多大伙伴希望快速…

制作前的关键筹备:考试考核系统之核心要点

明确系统使用目的​ 制作考试考核系统前&#xff0c;企业需明确系统使用目的&#xff0c;这是开发基石&#xff0c;不同目的决定系统功能特性。用于员工培训考核时&#xff0c;系统要与培训内容结合&#xff0c;能生成相应考题&#xff0c;检验员工知识掌握程度&#xff0c;具备…

Springboot把外部jar包打包进最终的jar包,并实现上传服务器

1、创建lib目录&#xff0c;把jar包放进这个目录下&#xff0c;然后标记lib目录为“资源根路径”&#xff08;鼠标右键lib目录->将目录标记为->资源根路径。之后lib文件夹会有如下的图标变化&#xff09; 文件结构如下&#xff1a; 2、pom文件添加依赖 <dependency…

内容中台的核心架构是什么?

数据中枢与服务API架构 在内容中台的核心架构中&#xff0c;数据中枢作为基础层&#xff0c;通过统一的数据模型与标准化接口&#xff0c;实现多源内容的集中存储与治理。其核心能力体现在对结构化与非结构化数据的清洗、分类及跨系统同步&#xff0c;例如整合企业内部的CRM、…

Light RPC:一款轻量高效的Java RPC框架实践指南

Light RPC&#xff1a;一款轻量高效的Java RPC框架实践指南 一、框架简介二、快速入门1. 环境准备2. 服务端配置2.1 添加依赖2.2 YAML配置2.3 接口与实现 3. 客户端配置3.1 添加依赖3.2 YAML配置3.3 客户端调用 三、核心设计解析四、适用场景与优势对比五、总结 一、框架简介 …

Hologres实时数仓在B站游戏的建设与实践

一、背景 实时数据仓库是近年来数据技术领域内的一大发展潮流。构建一个能够实现高吞吐量写入与更新、端到端全链路实时处理以及低延迟、高并发的实时数据仓库&#xff0c;一直是众多企业面临的重大挑战。随着B站游戏业务的快速发展&#xff0c;对数据的实时应用需求也日益增加…

Android WiFi协议之P2P介绍与实践

Android WiFi P2P WiFi P2P (Peer-to-Peer) 是 Android 提供的一种允许设备之间直接通过 WiFi 进行通信的技术&#xff0c;无需接入传统的 WiFi 网络或互联网。这种技术也被称为 WiFi Direct。 一、WiFi P2P 基本概念 1. 核心组件 P2P 设备&#xff1a;支持 WiFi P2P 的 And…

浅谈在HTTP中GET与POST的区别

从 HTTP 报文来看&#xff1a; GET请求方式将请求信息放在 URL 后面&#xff0c;请求信息和 URL 之间以 &#xff1f;隔开&#xff0c;请求信息的格式为键值对&#xff0c;这种请求方式将请求信息直接暴露在 URL 中&#xff0c;安全性比较低。另外从报文结构上来看&#xff0c…

若依微服务集成Flowable仿钉钉工作流

项目简介 本项目工作流模块集成在若依项目单独一个模块&#xff0c;可实现单独运行部署&#xff0c; 前端采用微前端&#xff0c;嵌入在若依的前端项目中。因博主是后端开发&#xff0c;对前端不是太属性&#xff0c;没将工作流模块前端代码移到若依前端。下面贴上代码工程结构…

WPS JS宏编程教程(从基础到进阶)-- 第六部分:JS集合与映射在 WPS 的应用

目录 第6章 JS集合与映射在 WPS 的应用6-1 集合的创建(实例:唯一值提取)示例代码详细解析Excel 环境模拟说明6-2 集合的不重复特性应用(案例:提取唯一值记录)示例代码详细解析案例说明6-3 集合成员添加与删除示例代码代码解析直观示意(Excel 模拟表格)6-4 集合成员添加…

MySQL 约束(入门版)

目录 一、约束的基本概念 二、约束演示 三、外键约束 &#xff08;一&#xff09;介绍 &#xff08;二&#xff09;外键约束语法 &#xff08;三&#xff09;删除/更新行为 一、约束的基本概念 1、概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储…

【ISP】ISP pipeline(AI)

ISP Pipeline 全流程概览 ISP&#xff08;Image Signal Processing&#xff0c;图像信号处理&#xff09;流程通常从原始 Bayer 数据出发&#xff0c;经过一系列模块处理&#xff0c;逐步完成图像校正和增强&#xff0c;最终生成用于显示或编码的标准图像。常见处理模块包括&a…

【Rust开发】Rust快速入门,开发出Rust的第一个Hello World

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Google Chrome下载受限制的解决方案【方法指南】

在国内使用网络时&#xff0c;部分用户在尝试访问Google Chrome官网下载谷歌浏览器时&#xff0c;常常遇到网页无法打开或文件下载失败的情况。这种下载受限制的问题多由网络访问政策或DNS解析异常导致。为了正常获取Google Chrome的最新版安装程序&#xff0c;用户需要通过一些…

使用 new EventSource 实现前端实时通信

示例&#xff1a; eventSource单向通信 1. 什么是 EventSource&#xff1f; EventSource 是浏览器提供的一种实现服务器推送&#xff08;Server-Sent Events&#xff0c;简称 SSE&#xff09;功能的 API。它是基于 HTTP 协议的单向通信机制&#xff0c;可以通过服务器将实时数…

Android Input——查找并添加目标窗口(七)

在 Android 输入系统中,InputDispatcher 的核心职责之一是将输入事件正确地传递到目标窗口。上一篇文章我们介绍到 InputDispatcher 事件分发调用到 findFocusedWindowTargetsLocked() 函数查找焦点窗口,并将焦点窗口添加到目标窗口,这里我们继续往下看。 一、获取焦点窗口…

Spring Boot中Spring MVC相关配置的详细描述及表格总结

以下是Spring Boot中Spring MVC相关配置的详细描述及表格总结&#xff1a; Spring MVC 配置项详解 1. 异步请求配置 spring.mvc.async.request-timeout 描述&#xff1a;设置异步请求的超时时间&#xff08;单位&#xff1a;毫秒&#xff09;。默认值&#xff1a;未设置&…

HTTP GET 和 POST 请求有什么区别

HTTP 的 GET 和 POST 请求是两种常见的 HTTP 请求方法&#xff0c;它们有不同的特点和应用场景。以下是它们的主要区别&#xff1a; 1. 用途 GET&#xff1a;用于从服务器获取数据或资源。GET 请求会附带查询参数在 URL 中&#xff0c;通常用于请求数据&#xff0c;如加载网页…