【例9.17】货币框架(信息学奥赛一本通- P1273)

news/2026/1/19 18:28:22/文章来源:https://www.cnblogs.com/yangykaifa/p/19503327

【题目描述】

给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。

【输入】

第一行为n和m;

下面n行为具体的面值。

【输出】

一行,方案数。

【输入样例】

3 10        //3种面值组成面值为10的方案
1           //面值1
2           //面值2
5           //面值5

【输出样例】

10          //有10种方案

【提示】

全部数据

n≤20,m≤4000。

解题思路

1. 状态定义

集合:选择货币的方案

限制:选择哪些种类面值的货币,凑多少钱

属性:货币面值加和

条件:等于m

统计量:方案数

状态定义dp[i][j]表示在前i种货币中选择货币凑j元钱的方案数。

初始状态:前i种货币中选择货币凑0元的方案数为1(不选任何货币也算一种方案),即dp[i][0] = 1

2. 状态转移方程

记第i种货币的面值为a[i]

集合:在前i种货币中选择货币凑j元钱的方案。

分割集合:是否选择第i种面值的货币

子集1:如果不选择第i种面值的货币,那么在前i种货币中选择货币凑j元的方案数,为在前i-1种货币中选择货币凑j元的方案数,即dp[i-1][j]

子集2:在要凑的钱数j大于等于第i种货币的面值a[i]的情况下,如果选择第i种货币,下一次还可以选择第i种货币。那么还需要在前i种货币中选择货币凑j-a[i]元。在前i种货币中选择货币凑j元的方案数,为在前i种货币中选择货币凑j-a[i]元的方案数,即dp[i][j-a[i]]

以上两种情况得到的方案数加和,即为在前i种货币中选择货币凑j元的方案数:

dp[i][j] = dp[i-1][j] + dp[i][j-a[i]]  (当j >= a[i])
dp[i][j] = dp[i-1][j]                  (当j < a[i])
/*
#include 
using namespace std;
long long dp[21][4001];//dp[i][j]代表有i种面值可以选时 组成面值j的方案数 这里一定要用longlong,不然方案数很快就超了
int a[21];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=0;i<=n;i++) dp[i][0]=1;//不管有多少种面值货币,组成面值为0的货币都只有0种方案for(int i=1;i<=n;i++){//遍历货币系统面值for(int j=1;j<=m;j++){//遍历要组成的货币面值dp[i][j]=dp[i-1][j];//先继承前面的方案数if(j>=a[i]) dp[i][j]=dp[i][j]+dp[i][j-a[i]];}}cout<
using namespace std;
int n,m;
int a[21];
long long dp[4001];
int main(){cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];dp[0]=1;for(int i=1;i<=n;i++){//n轮,每轮更新数据,因为dp[i]只与dp[i-1]有关for(int j=1;j<=m;j++){if(j>=a[i])//要组成的面值j>=a[i]代表第i种纸币才会开始派上用场,小于时派不上用场所以方案数跟上一轮是一样的dp[j]=dp[j]+dp[j-a[i]];}}cout<

一维数组为什么这么写我们把它拆解成三个最核心的逻辑概念来理顺:

1. 这里的 dp 数组到底存的是什么?

dp 数组想象成一个记账本

  • dp[j] 的含义是:“此时此刻,我有多少种方法凑出金额 j

  • 最开始,dp[0] = 1(凑出 0 元有一种方法:什么都不拿),其他全是 0。

2. 外层循环:上帝视角(逐个解锁硬币)

for(int i=1; i<=n; i++)

这个循环的意思是:“世界在进化”

  • 第 1 轮(i=1): 这个世界只有第 1 种硬币(比如 1 元)。跑完内层循环后,dp 数组记录的是“只用 1 元硬币凑各个金额的方法数”。

  • 第 2 轮(i=2): 上帝解锁了第 2 种硬币(比如 2 元)。我们在“只用 1 元”的基础上,去计算“加入了 2 元后”的新方法数。

  • 第 n 轮: 所有硬币都解锁了,最终结果出炉。

这就是为什么代码能行:它不是一下子算出来的,而是一层层“涂”上去的

3. 内层循环:最关键的“继承与更新”

for(int j=1; j<=m; j++) {if(j >= a[i])dp[j] = dp[j] + dp[j - a[i]];
}

这行代码 dp[j] = dp[j] + dp[j - a[i]] 其实包含了两层含义,我们把它拆开读:

第一层含义:dp[j] (等号右边的旧值) —— 继承
  • 在这一轮 i 开始之前,dp[j] 里存着什么?

  • 存着**“不使用当前硬币 a[i] 就能凑出 j 的方法数”**。

  • 逻辑: 既然我不打算用新硬币,那以前能凑出的方法,现在依然有效,我要保留下来。

第二层含义:dp[j - a[i]] —— 使用新硬币
  • 这表示:如果我一定要用至少一枚当前的硬币 a[i],那还剩下 j - a[i] 的金额需要凑。

  • 那么,凑出 j - a[i] 有多少种方法,就意味着我就增加了多少种凑出 j 的新路子。

第三层含义:正序循环 (从小到大) 的魔法 —— 无限使用

这是最烧脑的地方。为什么要从 1 循环到 m

举个例子:a[i] = 2 (2元硬币),我们算 dp[4]

  1. dp[2] 时: 我们加上了 dp[0](用了一枚 2 元)。此时 dp[2] 已经包含了“有 2 元硬币”的情况。

  2. dp[4] 时: 代码是 dp[4] += dp[4-2]dp[4] += dp[2]

  3. 注意! 这里的 dp[2]刚刚被更新过的(里面已经用过一枚 2 元了)。

  4. 当我们把这个“新 dp[2]”加到 dp[4] 里时,实际上是在已经用了一枚 2 元的基础上,又加了一枚 2 元(共两枚)。

结论:

  • 正序循环 (1 -> m): 当你算大金额 j 时,引用的小金额 j - a[i] 已经加过当前硬币了。这意味着你可以在一个硬币的基础上再叠一个,从而实现**“无限使用”**(完全背包)。

  • 倒序循环 (m -> 1): 当你算大金额 j 时,引用的小金额 j - a[i] 还是上一轮(旧世界)的值。这意味着你只能用这枚硬币一次(0/1 背包)。

模拟一张图,彻底理顺

假设我们要凑 4 元。 目前 dp 数组是:[1, 0, 0, 0, 0] (下标 0~4) 第一轮:解锁 1 元硬币

  • j=1: dp[1] += dp[0] -> 1 (1)

  • j=2: dp[2] += dp[1] -> 1 (1+1)

  • ...

  • 结束时 dp 全是 1。含义:全用 1 元硬币,每种金额只有 1 种凑法。

第二轮:解锁 2 元硬币 (重点来了!) 此时 dp 初始状态(继承自上一轮):[1, 1, 1, 1, 1]

  • j=2:

    • dp[2] = dp[2](旧, 1+1) + dp[0](新, 直接拿个2元)

    • dp[2] = 1 + 1 = 2 种。

    • 注意:现在 dp[2] 里包含了“1+1”和“2”两种情况。

  • j=3:

    • dp[3] = dp[3](旧, 1+1+1) + dp[1](新, 拿个2元+剩下的1元)

    • dp[3] = 1 + 1 = 2 种。

  • j=4:

    • dp[4] = dp[4](旧, 1+1+1+1) + dp[2](新)

    • 关键点:这里的 dp[2] 是刚才更新过的 2

    • 2 种方法分别是:(1+1) 和 (2)。

    • 我们在它们基础上再加个 2 元,变成了:(1+1 +2) 和 (2 +2)。

    • 加上旧的 (1+1+1+1),dp[4] 变成了 3 种。

总结

这个逻辑之所以通顺,是因为它完成了一个分类讨论: 凑出金额 j 的方案总数 = 完全不用当前硬币的方案数 (继承旧值) +至少用了一枚当前硬币的方案数 (累加新值)。

你写这段代码的时候,就像在对每一个金额 j 说:“嘿,如果我以前能凑出 j,那算数;如果我能先凑出 j-a[i],再补上一张 a[i],这也算一种新方法,都加进来!”

算法分析

关键点解析

为什么需要if(j >= a[i])判断?

这个条件判断是必不可少的,原因有二:

  1. 防止数组越界:当j < a[i]时,j - a[i]会变成负数,访问dp[负数]会导致未定义行为
  2. 逻辑正确性:只有当目标金额j大于等于当前货币面值a[i]时,才能使用该货币进行组合

复杂度分析

时间复杂度:O(n×m)

  • 空间复杂度
  • 二维数组解法:O(n×m)
  • 一维数组解法:O(m)(优化了空间复杂度)

算法优化思路

通过观察状态转移方程dp[i][j] = dp[i-1][j] + dp[i][j-a[i]],可以发现当前状态只与上一行和当前行的前面状态有关,因此可以使用滚动数组技术将空间复杂度从O(n×m)优化到O(m)。

这种优化在动态规划问题中很常见,特别是当状态转移只依赖于有限的前面状态时。

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

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

相关文章

PC5702恒频PWM低噪声12V/2A升压转换器1.2MHZ频率

概述&#xff1a;PC5702 是一款恒频脉冲宽度调制&#xff08;PWM&#xff09;低噪声升压转换器&#xff0c;专为常需本地生成高压的低压系统设计。该器件采用电流模式固定频率架构调节输出电压&#xff0c;具备快速瞬态响应和逐周期电流限制功能。PC5702 集成了欠压锁定、过压保…

AtomGit 亮相第五届 AIGC 开发者大会,链接产业新机遇

1 月 17 日&#xff0c;第五届 AIGC 开发者大会&#xff08;ACDC 2026&#xff09;在北京圆满落幕。作为开源生态与 AI 协同创新的重要参与者&#xff0c;AtomGit 受邀参会并设展&#xff0c;与千余名产学研专家、开发者及企业代表齐聚一堂&#xff0c;深度链接 AIGC 产业新机遇…

谷歌学术搜索:高效学术资源检索与文献管理工具指南

做科研的第一道坎&#xff0c;往往不是做实验&#xff0c;也不是写论文&#xff0c;而是——找文献。 很多新手科研小白会陷入一个怪圈&#xff1a;在知网、Google Scholar 上不断换关键词&#xff0c;结果要么信息过载&#xff0c;要么完全抓不到重点。今天分享几个长期使用的…

股票被套?别急着补仓!高手都在用这4步“解套”法

引言: 你是否经历过这样的场景&#xff1a;满怀信心地在10元价位买入一只股票&#xff0c;期待它一飞冲天&#xff0c;结果却眼睁睁看着它一路下跌到8元&#xff0c;甚至7元。那一刻&#xff0c;恐慌开始蔓延。对于大多数散户来说&#xff0c;第一反应几乎是本能的&#xff1a;…

计算机毕业设计springboot基于Vue.js的养老护理员直聘网站 智慧助老直聘平台——SpringBoot+Vue.js的护理人才撮合系统 基于SpringBoot与Vue的养老护理员即时匹配

计算机毕业设计springboot基于Vue.js的养老护理员直聘网站ep0ea16s &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。 我国正以前所未有的速度步入深度老龄化社会&#xff0c;60 岁…

Gaussian 计算分子偶极矩

一、什么是偶极矩偶极矩&#xff08;Dipole Moment&#xff09;是描述分子中电荷分布不对称程度的矢量物理量&#xff0c;定义为正负电荷中心之间的距离乘以电荷量。单位为Debye&#xff08;D&#xff09;。它的大小反映分子极性&#xff08;数值越大&#xff0c;极性越强&…

大连施耐德电气怎么选?2026年厂家实力大评测,电气自动化/施耐德电气/工控产品/中低压电气,施耐德电气实力厂家有哪些 - 品牌推荐师

评测背景 施耐德电气作为全球能效管理与自动化领域的领导者,其产品广泛应用于工业、能源、建筑、交通等核心领域。随着东北地区电气自动化需求的持续增长,大连及周边市场对施耐德电气正品供应、技术适配性及服务响应…

计算机毕业设计springboot基于的环境保护宣传网站 基于 SpringBoot 的“绿色地球”环保资讯与互动平台 基于 SpringBoot 的“绿行”生态环保科普与活动报名系统

计算机毕业设计springboot基于的环境保护宣传网站6201tc7h &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。当雾霾遮挡了蓝天、塑料漂满了海面&#xff0c;人们终于意识到&#x…

GAG:超越RAG,无需检索的私有知识注入新范式

主要关注LLM、RAG、Agent等AI前沿技术&#xff0c;每天分享业界最新成果和实战案例。 在生物医药、材料、金融等高价值私有场景&#xff0c;大模型必须掌握专有、快速演化、公开语料严重不足的知识。主流两条路线各有硬伤&#xff1a; 路线硬伤继续微调迭代贵、灾难性遗忘、通…

2026年行业内评价好的法兰企业选哪家,双相钢法兰/不锈钢法兰/变压器法兰/法兰/船用法兰/锻件,法兰源头厂家哪家好 - 品牌推荐师

当前,法兰作为管道连接的核心部件,其质量直接影响工业系统的安全与效率。随着石化、船舶、核电等领域对高精度、耐腐蚀法兰的需求激增,企业如何在技术迭代、交付能力与成本控制间找到平衡点,成为采购方关注的焦点。…

分子蒸馏设备“谁家强”?深度解析市场标杆与您的精明选择 - 品牌推荐大师1

在追求高纯度、高附加值的精细化工、生物医药及新材料领域,分离纯化技术如同交响乐团的指挥,决定着最终产品的“音准”。分子蒸馏,作为其中一项在高真空、低温度下实现温和分离的关键技术,其设备性能的优劣,直接关…

AI进入“研究时代“!零门槛多模态强化学习框架RLLaVA,小白也能玩转大模型

OpenAI 联合创始人 Ilya Sutskever 在最近的访谈中指出&#xff0c;AI 已经从单纯堆算力的“规模扩张时代&#xff08;Scaling Era&#xff09;”回到了“研究时代&#xff08;Research Era&#xff09;”。 在这一背景下&#xff0c;强化学习&#xff08;RL&#xff09;正在从…

酷秒神马9.0 2026最新版源码系统:技术升级与场景适配全解析

各位行业同仁&#xff0c;今天给大家深度拆解酷秒神马9.0 2026最新版源码系统的核心亮点。这款新版系统聚焦架构优化、多端兼容与运维简化&#xff0c;技术点不晦涩&#xff0c;不管是开发新手还是资深从业者&#xff0c;都能快速get实用价值&#xff0c;适配多场景部署需求。 …

选购指南:如何找到靠谱的清洗机生产厂家?吨包输送机/上料提升机/食品网带/链板输送机/连续上料机,清洗机生产商 - 品牌推荐师

随着工业自动化与清洁需求的升级,清洗机已成为食品加工、玻璃制造、冶金化工等领域的关键设备。然而,市场品牌林立、技术参差不齐,如何筛选出兼具技术实力与生产能力的可靠厂家?本文基于公开数据、市场调研及行业口…

【必藏】AI封神时代:为什么2026年只会写代码的程序员将被淘汰

前几天的时候&#xff0c;我在 X&#xff08;推特&#xff09; 上看到一个博主&#xff0c;叫&#xff1a;在悉尼和稀泥&#xff0c;他写了一篇文章&#xff0c;标题挺炸裂的&#xff0c;叫&#xff1a;《2026 年&#xff0c;为什么你最不应该做程序员》。 这个观点乍一听很反常…

艾体宝新闻 | Redis 月度更新速览:2025 年 12 月

&#x1f4ca; Redis Cloud 成本报表 API 正式 GA Redis Cloud 现已推出成本报告 API&#xff08;Cost Report API&#xff09;&#xff0c;让你能够直接、自动地获取账单数据&#xff0c;而无需再依赖手动从管理界面下载。 该 API 基于 FinOps 开放成本与使用规范&#xff0…

2026年目前评价高的沸石转轮销售厂家口碑推荐,沸石转轮/旋风除尘器/催化燃烧,沸石转轮批发厂家口碑排行榜 - 品牌推荐师

随着国家环保政策日趋严格,VOCs(挥发性有机物)治理已成为众多工业企业必须面对的课题。在众多治理技术中,沸石转轮吸附浓缩技术因其高净化效率、低运行能耗、安全稳定等核心优势,成为处理大风量、低浓度工业废气的…

企业级AI Agent构建全攻略:核心技术、架构设计与工程化实践,建议收藏

很多企业在聊 AI Agent 的时候&#xff0c;容易陷入两个极端&#xff1a;要么把它当成“更聪明的聊天机器人”&#xff0c;做完一个对话入口就宣布成功&#xff1b;要么一上来就堆满多智能体、工作流、向量库、知识图谱&#xff0c;最后发现系统很炫&#xff0c;但业务并没有更…

2026 四川桃树苗基地怎么选?扎根川内的优质选择 + 全链支持 种植少走弯路 - 深度智识库

2025 年四川桃树苗市场需求同比增长 18%,这一数据背后是越来越多种植户投身特色果业的热情。但川内地形气候差异显著,川东丘陵干旱少雨、川西高原低温寡照、川南多雨潮湿,不同区域对桃树苗的适应性要求截然不同。更…

全网最全8个AI论文平台,MBA高效写作必备!

全网最全8个AI论文平台&#xff0c;MBA高效写作必备&#xff01; AI 工具如何助力论文写作&#xff1f; 在当今信息爆炸的时代&#xff0c;MBA 学习者和研究者面临着越来越高的学术写作要求。无论是撰写案例分析、商业计划书还是研究论文&#xff0c;高效、准确的写作工具已成…