1 当贪心不再起效的时候

  对于换零钱问题,最简单也是性能最好的方法就是贪心算法。可是贪心算法一定要满足面值相邻两个零钱至少为二倍关系的前提条件。例如1,2,5,10,20……这样的零钱组应用贪心最简单;可对于1,3,4,5,6,10……这样的零钱组就不起效了:当目标总值是12的时候,应用贪心算法:答案是10x1+1x2,共3张,可正确答案应该是6x2共两张。

  那怎么解决呢?这样的问题符合动态规划的特点:任何一个状态可以由前边的状态计算而得。

  定义问题(明确需求):一组不重复且升序排列零钱面额数组vector<int> c(共m个元素),目标面值:int n,求所需最少的零钱张数。

2 O(mn)空间复杂度DP算法

  就像背包问题。最经典的算法是生成一个(m+1)x(n+1)DP数组来保存中间值,其中dp[i][j]表示只利用第1~i种零钱凑成目标面值为j所需的最少零钱张数。

  我们很容易得出状态转移方程:

    dp[i][j]=min(0+dp[i-1][j],1+dp[i-1][j-1*c[i]],2+dp[i-1][j-2*c[i]], ······);

  从而很容易写出代码。

  但作为一个追(xian)求(de)卓(dan)越(teng)的程序员,我又怎么会满足于此?看起来时间复杂度O(mn)已经达到极至,可空间复杂度O(mn)好像可以继续优化!

3 O(n)空间复杂度DP算法

  由上边的状态转移方程,我们发现每个元素只用到了上一行的若干个元素。那其实我们很容易想到,一个大小为2*(n+1)的一维数组就足够了!

  状态转移方程:

    dp[index][j]=min(0+dp[1-index][j],1+dp[1-index][j-1*c[i]],2+dp[1-index][j-2*c[i]], ······);

  计算方法没有任何差别,但是空间复杂度却大大降低!

  不仅如此,对于有一些DP算法,每个元素的计算只需要用到当前行左边的元素和上一行相同列坐标元素的值(例如矩阵的最小最径的DP算法),这样的算法,我们可以直接用一个n+1的一维数组作为DP数组就够用了!

4 总结

  由此,我们可以总结出本文的中心思想:

  (1)一个二维DP算法,如果每个元素的计算只需要用到上一行的若干个元素的值的时候,我们都可以用两个一维DP数组来优化空间复杂度。

  (2)一个二维DP算法,如果每个元素的计算只需要用到当前行左边的元素和上一行相同列坐标元素的值的时候,我们都可以用一个一维DP数组来优化空间复杂度。

  (3)要多尝试降低二维DP算法的空间复杂度。

  鼓掌[逃]!

DP优化与换零钱问题的更多相关文章

  1. 小P的故事——神奇的换零钱&&人活着系列之平方数

    http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2777&cid=1219 这题不会,看了别人的代码 #include <iostre ...

  2. 子集和问题(应用--换零钱)POJ2229:Sumsets

    我一直在纠结换零钱这一类型的题目,今天好好絮叨一下,可以说他是背包的应用,也可以说他是单纯的dp.暂且称他为dp吧. 先上一道模板题目. sdut2777: 小P的故事——神奇的换零钱 题目描述 已知 ...

  3. SDUT3145:Integer division 1(换零钱背包)

    题目:传送门 题目描述 整数划分是一个非常经典的数学问题. 所谓整数划分,是指把一个正整数n写成为n=m1+m2+...+mi的形式,其中mi为正整数,并且1<=mi<=n,此时,{m1, ...

  4. 取数字(dp优化)

    取数字(dp优化) 给定n个整数\(a_i\),你需要从中选取若干个数,使得它们的和是m的倍数.问有多少种方案.有多个询问,每次询问一个的m对应的答案. \(1\le n\le 200000,1\le ...

  5. 51nod 1101 换零钱 【完全背包变形/无限件可取】

    1101 换零钱  基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 ...

  6. 51 Nod 1101 换零钱(动态规划好题)

    1101 换零钱  基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 ...

  7. [总结]一些 DP 优化方法

    目录 注意本文未完结 写在前面 矩阵快速幂优化 前缀和优化 two-pointer 优化 决策单调性对一类 1D/1D DP 的优化 \(w(i,j)\) 只含 \(i\) 和 \(j\) 的项--单 ...

  8. DP 优化方法大杂烩 & 做题记录 I.

    标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...

  9. DP 优化小技巧

    收录一些比较冷门的 DP 优化方法. 1. 树上依赖性背包 树上依赖性背包形如在树上选出若干个物品做背包问题,满足这些物品连通.由于 01 背包,多重背包和完全背包均可以在 \(\mathcal{O} ...

随机推荐

  1. 把DATATABLE,DS中的内容用HTML的方式显示

    前几天,在搞一个数据显示的时候,因为是不固定的列的,所以需要动态创建列,这里面就运用一下,直接把数据库的Table显示在Html上,有两种方法,但是都有相应的缺点,第一个,如果内容太多,长度不好控制, ...

  2. Ubuntu杂记——Ubuntu自带拼音输入发杂乱不堪

    打开终端,用管理员权限输入ibus-daemon -drx,重启即可

  3. Android随笔之——PackageManager详解

    参考:http://www.cnblogs.com/xingfuzzhd/p/3374504.html 今天要讲的是PackageManager.Android系统为我们提供了很多服务管理的类,包括A ...

  4. golang 字符串操作实例

    package main import s "strings" import "fmt" var p = fmt.Println func main() { p ...

  5. ZOJ Problem Set - 1350 The Drunk Jailer ac代码 memset

    这是一道很简单的题目,题目大概意思说下:就是有n个监狱(编号从1到n),第一次全部打开,第二次打开编号为2的倍数的,第三次打开编号为3的倍数的,以此类推...最后问你有几个监狱是打开的 题目中我使用了 ...

  6. Electron Angular 开发小记

    一介绍 electron分为主进程和渲染进程,主进程负责和原生交互,控制窗口等. 渲染进程就是普通网页.主进程和渲染进程可以通过ipcMain(主进程使用)及ipcRenderer(渲染进程用)通信 ...

  7. 【JUC】JDK1.8源码分析之ConcurrentSkipListMap(二)

    一.前言 最近在做项目的同时也在修复之前项目的一些Bug,所以忙得没有时间看源代码,今天都完成得差不多了,所以又开始源码分析之路,也着笔记录下ConcurrentSkipListMap的源码的分析过程 ...

  8. WPF老矣,尚能饭否——且说说WPF今生未来(中):策略

    本文接上文<WPF老矣,尚能饭否——且说说WPF今生未来(上):担心>继续. “上篇”中部分精彩的点评: 虽然WPF不再更新了,但是基于WPF的技术还是在发展着,就比如现在的WinRT,只 ...

  9. 关于SQL储存过程中输出多行数据

    declare @num1 int           --为符合条件的总行数 select @num1=COUNT(1) from cardInfo where openDate between @ ...

  10. C# .NET Socket封装

    Socket封装,支持多客户端,支持大文件传输,支持多线程并发,对较大的Socket包进行分块传输. 封装所要达到的效果,是可以像下面这样使用Socket和服务端通信,调用服务端的方法,让你在使用So ...