首页/新闻资讯/正文详情

动态规划解决NOIP摆花问题:多重背包变种应用

发布时间:2026/11/5 0:03:07 来源:云帆数科 栏目:资讯中心
动态规划解决NOIP摆花问题:多重背包变种应用
1. 题目背景与核心需求解析这道来自NOIP 2012普及组的摆花题目描述了一个典型的花店陈列场景小明需要将n种花共m盆摆成一排要求同种花必须相邻且按编号顺序排列同时每种花i的数量不能超过a_i盆。我们需要计算出所有符合条件的摆花方案数并对10^67取模。1.1 问题建模这实际上是一个带约束条件的组合数学问题可以转化为有n种不同的花第i种花最多使用a_i盆总共使用恰好m盆花同种花必须连续摆放不同种类花按编号升序排列关键约束在于同种花连续和按编号顺序这两个条件这使得问题可以转化为一个多重背包问题的变种。1.2 输入输出分析输入格式第一行n m花的种类数和总盆数第二行a_1 a_2 ... a_n每种花的最大使用量输出要求方案数对1,000,007取模2. 动态规划解法详解2.1 状态定义我们定义dp[i][j]表示使用前i种花摆放j盆花的方案数。其中i ∈ [1, n]j ∈ [0, m]2.2 状态转移方程对于第i种花我们可以选择使用0到a_i盆因此状态转移方程为 dp[i][j] Σ dp[i-1][j-k] 其中k ∈ [0, min(a_i, j)]边界条件dp[0][0] 1使用0种花摆放0盆的方案数为1dp[0][j] 0, j 0使用0种花不可能摆放多于0盆2.3 算法实现步骤初始化dp数组为0设置dp[0][0]1双重循环外层循环i从1到n花的种类内层循环j从0到m总盆数对于每个j枚举k从0到min(a_i, j)累加方案数dp[i][j] dp[i-1][j-k]最终结果为dp[n][m] % MOD2.4 空间优化技巧由于每次只用到前一种花的状态可以使用滚动数组优化空间只维护一个一维数组dp[j]内层循环j需要从大到小遍历避免覆盖优化后的伪代码dp [0]*(m1) dp[0] 1 for i in range(1, n1): for j in range(m, -1, -1): upper min(a[i], j) for k in range(1, upper1): dp[j] dp[j-k] dp[j] % MOD3. 代码实现与细节处理3.1 C完整实现#include iostream #include algorithm using namespace std; const int MOD 1e6 7; int main() { int n, m; cin n m; int a[n1]; for(int i1; in; i) cin a[i]; int dp[n1][m1] {0}; dp[0][0] 1; for(int i1; in; i) { for(int j0; jm; j) { int upper min(a[i], j); for(int k0; kupper; k) { dp[i][j] (dp[i][j] dp[i-1][j-k]) % MOD; } } } cout dp[n][m] endl; return 0; }3.2 Python优化实现MOD 10**6 7 n, m map(int, input().split()) a list(map(int, input().split())) a [0] a # 使下标从1开始 dp [0] * (m 1) dp[0] 1 for i in range(1, n1): for j in range(m, -1, -1): upper min(a[i], j) for k in range(1, upper1): dp[j] (dp[j] dp[j - k]) % MOD print(dp[m])3.3 关键细节说明数组下标处理通常将a和dp数组的下标从1开始方便对应花的种类模运算位置在每次加法后立即取模防止整数溢出边界条件检查特别注意j0和i0的情况输入处理注意题目给出的输入格式特别是多个空格分隔的情况4. 算法优化与性能分析4.1 时间复杂度优化原始三重循环的时间复杂度为O(nmmax(a_i))当a_i较大时效率不高。可以通过前缀和优化计算前缀和数组sum_dp[i][j] Σ dp[i][0..j]状态转移可以表示为 dp[i][j] sum_dp[i-1][j] - sum_dp[i-1][j-a_i-1] (当ja_i) 或 sum_dp[i-1][j] (当j≤a_i)这样时间复杂度降为O(n*m)4.2 优化后的C实现#include iostream #include algorithm using namespace std; const int MOD 1e6 7; int main() { int n, m; cin n m; int a[n1]; for(int i1; in; i) cin a[i]; int dp[n1][m1] {0}; int sum[n1][m1] {0}; dp[0][0] 1; // 初始化前缀和 for(int j0; jm; j) sum[0][j] 1; for(int i1; in; i) { for(int j0; jm; j) { int L j - a[i] - 1; if(L 0) dp[i][j] sum[i-1][j]; else dp[i][j] (sum[i-1][j] - sum[i-1][L] MOD) % MOD; // 计算前缀和 if(j 0) sum[i][j] dp[i][j]; else sum[i][j] (sum[i][j-1] dp[i][j]) % MOD; } } cout dp[n][m] endl; return 0; }4.3 性能对比方法时间复杂度空间复杂度适合数据范围基础DPO(nmmax(a_i))O(n*m)n,m≤100, a_i≤10滚动数组O(nmmax(a_i))O(m)n,m≤1000, a_i≤100前缀和优化O(n*m)O(n*m)n,m≤10^4, a_i≤10^45. 常见错误与调试技巧5.1 典型错误案例数组越界忘记处理j-k为负的情况数组下标从0开始还是1开始混乱模运算错误只在最后取模中间结果溢出减法取模时忘记加MOD再取模初始化错误忘记初始化dp[0][0]1错误地将所有dp[i][0]初始化为15.2 调试建议小数据测试例如n2,m3,a[1,2]手工计算应有方案[0,3],[1,2]结果应为2打印中间状态输出dp表格检查状态转移是否正确特别检查边界情况(j0和i0)性能测试使用极端数据测试(n100,m100,a_i100)检查是否在合理时间内完成5.3 洛谷提交注意事项输入输出使用cin/cout可能需要关闭同步流或者使用更快的scanf/printf内存限制注意n和m的范围大数组尽量定义为全局变量特殊用例测试n1的情况测试m0的情况测试a_i0的情况6. 算法扩展与变种思考6.1 变种问题1取消排列顺序限制如果取消不同种类花按编号顺序排列的限制问题变为多重集合排列问题公式为m!/(k1!k2!...kn!)其中Σkim, ki≤a_i需要使用容斥原理计算6.2 变种问题2每种花至少摆一盆增加约束每种花至少摆一盆修改状态转移k从1开始而不是0初始条件变化dp[0][0]1, 其他dp[0][j]06.3 变种问题3三维DP扩展如果增加新的维度如花的颜色、高度等属性定义dp[i][j][k]等多维状态状态转移方程相应扩展可能需要使用记忆化搜索简化实现在实际比赛中理解基础DP模型后可以灵活应对各种变种题目。建议多练习类似题目如背包问题、组合计数问题等培养对状态设计和转移的敏感度。

相关推荐

AI智能体重写投研工作流:分析师如何从数据搬运工转型为判断者
AI智能体重写投研工作流:分析师如何从数据搬运工转型为判断者

1. 投研圈最近吵翻天的那个问题前阵子跟几个做投研的朋友吃饭,席间有个刚入行两年的小朋友问了一句:"现在AI这么猛,我们是不是快失业了?"桌上瞬间安静了两秒,然后一个做了十几年卖方研究的老哥笑了笑说&… · 2026/11/4 23:30:23

Gemini 3.1 Pro与Nano Banana 2实测:多模态推理与图像生成能力深度解析
Gemini 3.1 Pro与Nano Banana 2实测:多模态推理与图像生成能力深度解析

1. 这次发布到底带来了什么变化谷歌把 Gemini 3.1 Pro 和 Nano Banana 2 放在同一场发布里推出来,这个组合本身就值得琢磨。一个是通用推理能力的主力升级,一个是图像生成方向的专项迭代,两条线同时推进,说明谷歌在多模态这条路上… · 2026/11/5 3:47:40

STBC空时分组码原理、线性合并译码与BER仿真实践
STBC空时分组码原理、线性合并译码与BER仿真实践

简介:面向无线通信入门学习者与课程实验需求,这套空时分组码(STBC)编码译码实现代码围绕发射端空时编码与接收端译码过程展开,并给出误码率(BER)曲线用于直观验证算法效果。资源包共3个文件&… · 2026/11/5 1:30:13

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析
EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被… · 2026/11/5 16:49:35

Rust原来很简单二:所有权系统
Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6… · 2026/11/5 16:26:08

基于Hadoop+Spark的民宿智能推荐系统设计与实现
基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

UART接口24位ADC搭配RS485,解决远距离温度监控难题
UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

多智能体协作系统架构设计与实践优化
多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39

大模型系统性入门实战指南:从原理到部署微调的全链路路线
大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39

鸿蒙文件系统沙箱机制解析与开发实践
鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码