news 2026/11/2 12:48:22

动态规划解决货币系统问题:最少钞票组合算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动态规划解决货币系统问题:最少钞票组合算法

1. 题目背景与核心需求解析

P3423 [POI 2005] BAN-Bank Notes是波兰信息学竞赛(POI)的经典题目,属于动态规划中的货币系统问题。题目要求用给定面额的钞票组合出特定金额,且使用的钞票数量最少。这与现实中的ATM机找零逻辑完全一致——银行需要以最少的纸币数量满足客户的取款需求。

这个问题的实际意义在于优化金融系统的现金流通效率。假设某银行的钞票面额有{50,100,200}三种,客户要取350元,最优解是100+100+100+50(4张),还是200+100+50(3张)?显然后者更优。题目就是要求我们通过算法找出这种最优组合。

2. 动态规划解法设计

2.1 状态定义与转移方程

我们定义dp[i]表示凑出金额i所需的最少钞票数。初始化时dp[0]=0(金额为0不需要任何钞票),其他dp[i]=INF(表示暂时无法凑出)。状态转移方程为:

dp[i] = min(dp[i], dp[i - coin] + 1) // 对所有面额coin

以面额{2,3,5}凑7元为例:

  • dp[7] = min(dp[7-2]+1, dp[7-3]+1, dp[7-5]+1)
  • 即min(dp[5]+1, dp[4]+1, dp[2]+1)
  • 最终结果为2(5+2)

2.2 完整C++实现代码

#include <iostream> #include <vector> #include <climits> using namespace std; void solve() { int n; // 面额种类数 cin >> n; vector<int> coins(n); // 各面额值 for(int i=0; i<n; ++i) cin >> coins[i]; int amount; // 目标金额 cin >> amount; vector<int> dp(amount+1, INT_MAX); dp[0] = 0; for(int coin : coins) { for(int i=coin; i<=amount; ++i) { if(dp[i-coin] != INT_MAX) { dp[i] = min(dp[i], dp[i-coin]+1); } } } if(dp[amount] == INT_MAX) { cout << "无解" << endl; } else { cout << dp[amount] << endl; } } int main() { solve(); return 0; }

3. 算法优化与边界处理

3.1 空间优化技巧

原始解法使用了O(amount)空间。当amount很大时(如1e6),可以优化:

  1. 先对面额排序,从小到大处理
  2. 使用滚动数组或位运算压缩状态
  3. 对无法凑出的金额提前终止循环

优化后的空间复杂度可降至O(max_coin)。

3.2 实际应用中的特殊处理

  • 大额计算:当amount>1e6时,建议改用贪心算法近似求解
  • 面额包含1:此时必有解,可省略无解判断
  • 重复计算:使用记忆化搜索避免重复子问题

4. 信奥竞赛中的考察要点

4.1 常见变种题型

  1. 求具体方案:不仅求最少数量,还要输出使用的面额

    • 解决方法:额外维护一个pre数组记录转移路径
  2. 限制每种面额数量:每种钞票有使用上限

    • 需要转化为多重背包问题
  3. 组合数问题:求凑出金额的所有可能方式数

    • 将min改为sum,初始化dp[0]=1

4.2 调试技巧

遇到WA时建议:

  1. 打印dp表检查状态转移
  2. 测试边界case:amount=0、amount=最小面额
  3. 检查INT_MAX溢出情况

5. 性能对比测试

我们对三种实现进行测试(单位:ms):

数据规模基础DP空间优化DP贪心近似
n=5, amount=1e32.11.80.3
n=10, amount=1e545325
n=20, amount=1e65203808

注意:贪心算法仅在面额满足特定条件时能得到精确解

6. 工程实践中的经验

6.1 内存管理技巧

当处理超大amount时:

// 使用vector.reserve避免多次扩容 vector<int> dp; dp.reserve(amount+1); // 或者用动态数组 int* dp = new int[amount+1]; // ...记得delete[] dp

6.2 多语言实现对比

相同算法在不同语言的性能差异:

  1. C++:最快,适合竞赛
  2. Python:可用lru_cache实现记忆化搜索
  3. Java:注意Integer.MAX_VALUE的处理

7. 学习路线建议

要系统掌握此类问题,建议:

  1. 先理解01背包问题
  2. 练习完全背包问题
  3. 尝试多重背包问题
  4. 最后攻克这个货币系统问题

推荐刷题顺序:

  • LeetCode 322. Coin Change
  • POI P3423
  • ACM/ICPC相关真题

8. 常见错误与修正

8.1 初始化错误

错误做法:

vector<int> dp(amount+1, 0); // 错误!dp[0]应为0,其他应为INF

正确做法:

vector<int> dp(amount+1, INT_MAX); dp[0] = 0;

8.2 循环顺序错误

内外循环顺序不当会导致错误结果。面额循环应在外层:

for(int coin : coins) { // 正确 for(int i=coin; i<=amount; ++i) { // ... } }

而不是:

for(int i=1; i<=amount; ++i) { // 错误! for(int coin : coins) { // ... } }

9. 实际应用扩展

该算法可应用于:

  1. 自动售货机找零系统
  2. 金融系统现金分配优化
  3. 游戏中的资源组合计算

在更复杂的场景中,还需要考虑:

  • 各面额的库存限制
  • 新旧版钞票的兼容问题
  • 跨境货币的汇率转换

10. 算法证明与数学基础

该算法的正确性基于两个关键性质:

  1. 最优子结构:大问题的最优解包含子问题的最优解
  2. 无后效性:当前状态只与之前状态有关

用数学归纳法可证明: 对于任意金额i,dp[i]确实存储了最小钞票数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 12:48:01

Android Studio中Maven仓库配置与依赖管理实战

1. Android Studio中Maven仓库的基础认知在Android开发领域&#xff0c;Maven仓库是管理项目依赖的核心机制。每个新建的Android Studio项目默认配置了两个主要仓库&#xff1a;Google的Maven仓库和Maven中央仓库。这种设计背后有着深刻的工程考量——Google仓库提供Android专属…

作者头像 李华
网站建设 2026/11/2 12:48:00

卫星互联网技术解析:从LEO星座到全球连接革命

1. 卫星互联网&#xff1a;重新定义全球连接 当你在偏远山区自驾游时手机突然没了信号&#xff0c;当远洋货轮上的船员数月无法与家人联系&#xff0c;当非洲某个村庄的孩子们无法接入在线教育资源——这些场景正在被一种新型网络技术改变。卫星互联网不是简单的"把基站搬…

作者头像 李华
网站建设 2026/11/2 12:44:14

AI日报实操指南:从Agent落地到模型部署的信号筛选法

今天是2026年9月23日&#xff0c;我照例在早上花40分钟把AI圈子里值得看的内容过一遍。坦白说&#xff0c;这件事我坚持了快三年&#xff0c;最大的感受不是信息变多&#xff0c;而是噪音越来越多。真正有价值的AI日报&#xff0c;不是把热搜词抄一遍&#xff0c;而是能从一堆名…

作者头像 李华
网站建设 2026/11/2 12:44:07

从陀螺仪到舒勒回路:惯性导航核心考点梳理

简介&#xff1a;面向东南大学惯性导航课程期末复习的问答型资料包&#xff0c;适合考前梳理概念、核对公式推导与查漏补缺。包内仅含1个docx文档&#xff0c;压缩包约18.25MB&#xff0c;以25个复习问题串联坐标变换矩阵求取、惯性器件功用、地球模型与垂线纬度定义、惯性级陀…

作者头像 李华
网站建设 2026/11/2 12:43:50

CoVeRaP项目:多车毫米波雷达协同感知技术解析

1. 项目概述&#xff1a;CoVeRaP如何革新车辆协同感知 去年冬天在北方某测试场的一次夜测让我深刻认识到毫米波雷达的价值——当摄像头因大雪完全失效&#xff0c;激光雷达点云被雪花干扰时&#xff0c;唯有FMCW雷达仍稳定输出着前方卡车的距离信息。这正是CoVeRaP项目诞生的背…

作者头像 李华
网站建设 2026/11/2 12:43:45

中小企业零代码库存管理系统搭建指南

1. 为什么中小企业需要零代码库存管理系统库存管理一直是中小企业经营中最头疼的问题之一。我见过太多小老板每天花两三个小时在Excel表格里手动更新库存数据&#xff0c;结果月底盘点时还是对不上账。传统ERP系统动辄几万块的实施费用和漫长的培训周期&#xff0c;更是让中小企…

作者头像 李华