NO.88十六届蓝桥杯备战|动态规划-多重背包|摆花(C++)
多重背包
多重背包问题有两种解法:
- 按照背包问题的常规分析⽅式,仿照完全背包,第三维枚举使⽤的个数;
- 利⽤⼆进制可以表⽰⼀定范围内整数的性质,转化成01 背包问题。
⼩建议:并不是所有的多重背包问题都能⽤⼆进制优化,⽽且优化版本的代码很⻓。因此,如果时间复杂度允许的情况下,能不优化就不优化
解法⼀:常规分析 - 状态表⽰:
dp[i][j]表⽰:从前i 个物品中挑选,总重量不超过j 的情况下,最⼤的价值。
dp[n][m]就是最终结果。 - 状态转移⽅程:
根据第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,并且不能按照完全背包的⽅式优化。 - 初始化:
全部为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][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 20∼2k能够表⽰区间[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 时的总⽅案数
正好是多重背包求⽅案数的模型,我们可以⽤多重背包的思考⽅式来解决这道题。
- 状态表⽰:
dp[i][j]表⽰:从前i个花中挑选,正好摆放j 个花盆时的⽅案数。 - 状态转移⽅程:
根据第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]
- 初始化:
dp[0][0] = 1,相当于起始状态,为了让后续的填表有意义,不然全都是0 。 - 填表顺序:
从上往下每⼀⾏,每⼀⾏从左往右。
这道题就不能⽤⼆进制优化,因为这道题的背包,限定条件和价值是⼀⼀对应的,并且求的是⽅案数。如果⽤⼆进制优化会统计多余的情况,⽐如:
- 有两个物品,个数分别是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;
}
相关文章:
NO.88十六届蓝桥杯备战|动态规划-多重背包|摆花(C++)
多重背包 多重背包问题有两种解法: 按照背包问题的常规分析⽅式,仿照完全背包,第三维枚举使⽤的个数;利⽤⼆进制可以表⽰⼀定范围内整数的性质,转化成01 背包问题。 ⼩建议:并不是所有的多重背包问题都能…...
vue项目打包里面pubilc里的 tinymce里的js文件问题
以下是解决 Vue 项目打包后 public/tinymce 中 JS 文件路径问题的完整方案: 问题原因 当使用 public 目录存放静态资源时,Vue CLI 默认会将 public 下的文件 直接复制到打包目录的根路径,但以下操作可能导致路径错误: 开发环境使…...
Python星球日记 - 第18天:小游戏开发(猜数字游戏)
🌟引言: 上一篇:Python星球日记 - 第17天:数据可视化 名人说:路漫漫其修远兮,吾将上下而求索。(屈原《离骚》) 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、游戏概述与原理1. 游戏基本规则2. 编程知识点3.猜数字游戏流程图二、游戏逻辑设计…...
爬虫抓包工具和PyExeJs模块
我们在处理一些网站的时候, 会遇到一些屏蔽F12, 以及只要按出浏览器的开发者工具就会关闭甚至死机的现象. 在遇到这类网站的时候. 我们可以使用抓包工具把页面上屏蔽开发者工具的代码给干掉. Fiddler和Charles 这两款工具是非常优秀的抓包工具. 他们可以监听到我们计算机上所…...
无人机击落技术难点与要点分析!
一、技术难点 1. 目标探测与识别 小型化和低空飞行:现代无人机体积小、飞行高度低(尤其在城市或复杂地形中),雷达和光学传感器难以有效探测。 隐身技术:部分高端无人机采用吸波材料或低可探测设计,进…...
2025年Java无服务器架构实战:AWS Lambda与Spring Cloud Function深度整合
摘要 📝 本文深入探讨如何在2025年Java生态中实现AWS Lambda与Spring Cloud Function的无缝整合。我们将从基础概念讲起,逐步深入到实际部署、性能优化和最佳实践,通过详实的代码示例展示如何构建高效、可扩展的无服务器Java应用。 目录 &a…...
LeetCode 题目 「二叉树的右视图」 中,如何从「中间存储」到「一步到位」实现代码的优化?
背景简介 在 LeetCode 的经典题目 「二叉树的右视图」 中,我们需要返回从右侧看一棵二叉树时所能看到的节点集合。每一层我们只能看到最右边的那个节点。 最初,我采用了一个常规思路:层序遍历 每层单独保存节点值 最后提取每层最后一个节…...
8.第二阶段x64游戏实战-string类
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:7.第二阶段x64游戏实战-分析人物属性 string类是字符串类,在计算机中…...
Go语言sync.Mutex包源码解读
互斥锁sync.Mutex是在并发程序中对共享资源进行访问控制的主要手段,对此Go语言提供了非常简单易用的机制。sync.Mutex为结构体类型,对外暴露Lock()、Unlock()、TryLock()三种方法,分别用于阻塞加锁、解锁、非阻塞加锁操作(加锁失败…...
C++实现文件断点续传:原理剖析与实战指南
文件传输示意图 一、断点续传的核心价值 1.1 大文件传输的痛点分析 网络闪断导致重复传输:平均重试3-5次。 传输进度不可回溯:用户无法查看历史进度。 带宽利用率低下:每次中断需从头开始。 1.2 断点续传技术优势 指标传统传输断点续传…...
MySQL中FIND_IN_SET函数与INSTR函数用法解析
一、功能定义与语法 1、FIND_IN_SET函数 语法:FIND_IN_SET(str, strlist) 功能:在逗号分隔的字符串列表(strlist)中查找精确匹配的子字符串(str),并返回其位置(从1开始)…...
Python贝叶斯回归、强化学习分析医疗健康数据拟合截断删失数据与参数估计3实例
全文链接:https://tecdat.cn/?p41391 在当今数据驱动的时代,数据科学家面临着处理各种复杂数据和构建有效模型的挑战。本专题合集聚焦于有序分类变量处理、截断与删失数据回归分析以及强化学习模型拟合等多个重要且具有挑战性的数据分析场景,…...
Git 协同开发的常用操作
1. 单仓库(多分支开发) 从远程拉取代码 git clone https://gitee.com/...查看当前分支 git branch -- *master创建并切换到你的开发分支(my-dev) git checkout -b my-dev查看当前分支 git branch -- marster -- *my-dev提交代…...
微信小程序 -- 原生封装table
文章目录 table.wxmltable.wxss注意 table.js注意 结果数据结构 最近菜鸟做微信小程序的一个查询功能,需要展示excel里面的数据,但是菜鸟找了一圈,也没发现什么组件库有table,毕竟手机端好像确实不太适合做table! 菜鸟…...
分布式文件存储系统FastDFS
文章目录 1 分布式文件存储1_分布式文件存储的由来2_常见的分布式存储框架 2 FastDFS介绍3 FastDFS安装1_拉取镜像文件2_构建Tracker服务3_构建Storage服务4_测试图片上传 4 客户端操作1_Fastdfs-java-client2_文件上传3_文件下载4_获取文件信息5_问题 5 SpringBoot整合 1 分布…...
ZKmall开源商城服务端验证:Jakarta Validation 详解
ZKmall开源商城基于Spring Boot 3构建,其服务端数据验证采用Jakarta Validation API(原JSR 380规范),通过声明式注解与自定义扩展机制实现高效、灵活的数据校验体系。以下从技术实现、核心能力、场景优化三个维度展开解析&#…...
深度分页及优化建议
深度分页的定义 深度分页是指在分页查询中,当用户请求非常靠后的页面时,数据库需要处理大量数据,导致查询性能显著下降的情况。例如,一个查询结果有 100 万条记录,而用户要查询第 999 页(每页 10 条记录&a…...
电网电能质量分析:原理、算法及实际应用
一、引言 在现代社会,电力供应的稳定性和可靠性对工业生产、社会生活的各个方面都至关重要。电能质量作为衡量电力系统供电能力的关键指标,其优劣直接影响到电力设备的运行效率、使用寿命以及生产过程的稳定性。随着电力系统规模的不断扩大,新…...
学透Spring Boot — 017. 魔术师—Http消息转换器
本文是我的专栏《学透Spring Boot》的第17篇文章,了解更多请移步我的专栏: 学透 Spring Boot_postnull咖啡的博客-CSDN博客 目录 HTTP请求和响应 需求—新的Media Type 实现—新的Media Type 定义转换器 注册转换器 编写Controller 测试新的medi…...
BOE(京东方)旗下控股子公司“京东方能源”成功挂牌新三板 以科技赋能零碳未来
2025年4月8日,BOE(京东方)旗下控股子公司京东方能源科技股份有限公司(以下简称“京东方能源”)正式通过全国中小企业股份转让系统审核,成功在新三板挂牌(证券简称:能源科技,证券代码:874526),成为BOE(京东方)自物联网转型以来首个独立孵化并成功挂牌的子公司。此次挂牌是BOE(京…...
Airflow集成Lark机器人
🥭1. 实现目标 🕐 通过自定义函数,实现Lark机器人告警功能 🕐 通过Lark机器人代替邮件数据的发送功能 🥭2.自定义函数实现 from airflow import DAG from airflow.operators.python_operator import PythonOperator from airflow.models import Variable import requ…...
Git使用与管理
一.基本操作 1.创建本地仓库 在对应文件目录下进行: git init 输入完上面的代码,所在文件目录下就会多一个名为 .git 的隐藏文件,该文件是Git用来跟踪和管理仓库的。 我们可以使用 tree 命令(注意要先下载tree插件)…...
计算机网络——传输层(Udp)
udp UDP(User Datagram Protocol,用户数据报协议 )是一种无连接的传输层协议,它在IP协议(互联网协议)之上工作,为应用程序提供了一种发送和接收数据报的基本方式。以下是UDP原理的详细解释&…...
网络安全小知识课堂(五)
病毒与蠕虫:你的电脑为何会 “生病” 和 “传染”? 引言 你是否见过这样的场景:电脑突然弹窗广告暴增,文件莫名消失,甚至整个公司网络集体瘫痪?这些症状背后,可能是 ** 病毒(Virus…...
图解Java设计模式
1、设计模式面试题 2、设计模式的重要性 3、7大设计原则介绍 3.1、单一职责原则...
wsl2+ubuntu22.04安装blender教程(详细教程)
本章教程介绍,如何在Windows操作系统上通过wsl2+ubuntu安装blender并运行教程。Blender 是一款免费、开源的 3D 创作套件,广泛应用于建模、动画、渲染、视频编辑、特效制作等领域。它由全球开发者社区共同维护,支持跨平台(Windows、macOS、Linux),功能强大且完全…...
其他合成方式介绍
在 SurfaceFlinger 的 Layer 处理逻辑中,除了常见的 Client Composition(GPU合成) 和 Device Composition(HWC合成),还存在一些特殊的合成方式,比如 Sideband、Solid Color 和 Display Decorati…...
Spring AI Alibaba MCP 市场正式上线!
Spring AI Alibaba 正式上线 MCP 市场:Spring AI Alibaba-阿里云Spring AI Alibaba官网官网。 开发者可以在这里搜索市面上可用的 MCP Server 服务,了解每个服务的实现与接入方法。 MCP 市场是做什么的? Spring AI Alibaba MCP 当前主要提供…...
Spring Security基本入门
1、为什么要使用权限框架 权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同的人访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题。 2、权限管理的常见…...
【Hadoop入门】Hadoop生态圈概述:核心组件与应用场景概述
1 Hadoop生态圈概述 Hadoop生态圈是以 HDFS(分布式存储) 和 YARN(资源调度) 为核心,围绕大数据存储、计算、管理、分析等需求发展出的一系列开源工具集合。 核心特点: 模块化:各组件专注解决特定…...
