简单暴力到dp的优化(入门篇)

原创 2018年04月16日 18:14:58

上篇,我们提到,遇到问题,首先根据定义写出笨方法,找出依赖关系(有些题这一步就不太简单,要自己归纳关系),然后进行优化,下面,我们通过几道此方面的经典的,较为简单的二维题目进行讲解,所谓二维,就是表示状态的参数有两个。

背包问题作为一个经典问题是很基础的一个题目老掉牙了,但是对萌新养成思维习惯,熟悉思维过程有些帮助,虽然有些题套路已经很成熟了,但是我还是想把当时我自己思考的思路写一下,当你自己经过思考想出了解法,然后发现和标准题解一样时,那种感觉真的不错。作为一个小白,我觉得,可能这就是它的魅力吧。(当然更多的是受挫)

萌新阶段,我们所谓的经典背包问题,保证了所有量化后的数据均为正整数,即是一个特殊的整数规划问题请百度背包九讲,讲解实在太多了,我就不写了。

 

还有,以后我会用心写,尽量用少的语言表达清楚,语言以后也会正式一些。

Ok,开始根据题来说明:

第一个萌新题

给定数组arr,  arr  中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,  再给定一个整数aim 代表要找的钱数,求组成aim 的最少货币数。

  [举例]

  arr=[5,2,3],  aim=20。

  4 张5 元可以组成20 元,其他的找钱方案都要使用更多张的货币,返回4。

arr=[5,2,3],  aim=0。

  不用任何货币就可以组成0 元,返回0。

  arr=[3,5],aim=2。

  根本无法组成2 元,钱不能找开的情况下默认返回-1。

(你要是想贪心就贪吧,反正我不贪)

定义f(a,b)代表的是a面值及之前的货币,组成b元的最少张数。那f(arr[-1],aim)就是我们想求的答案。现在分析,怎样通过前面的状态推出结果?对于货币arr[-1],我们可以一张都不用,那最少张数其实就是f(arr[-2],aim),我们也可以用一张arr[-1],最少张数就可能是f(arr[-2],aim-arr[-1])+1(用之前的钱组成aim-arr[-1]元钱,然后加一张arr[-1]),同理,我们可以用两张arr[-1],或者更多,直到下一个就超过aim的时候。所以我们应该在所有情况中选最小的,

归纳表达式:

f(a,b)=min(f(arr[a-1],b-k*arr[a])+k),k>=0,且b-k*arr[a]>=0

当然,以前也提到过,直接递归我们会有大量重复计算,所以需要记下来之前的结果供我们使用。有两个参数代表现在的状态,所以生成二维表。

l=[[0 for i in range(len(arr))] for i in range(aim+1)]

在这里吹一波py,左边是要生成的元素,右边写循环,几维表都是一行生成。

我们看,f(arr[a],b)和谁有关?和上一行,也就是arr[a-1]那一行的很多左边元素有关。

所以确定打表顺序,从上到下,从左到右,打表,一个一个打,l[a][b]=min(f(a-1,b-k*arr[a])+k),依次推出l[a][b],右下角就是答案。

 

但是,还是有相当多的重复计算,我们的l[a][b-arr[a]]其实就是根据除了l[a-1][b]的左边那些元素求的的最小值
所以l[a][b]=min(l[a][b-arr[a]]+1,l[a-1][b])。

其实和左边和上边元素相关的背包,还有一些别的题,都是如此。对于本物品,当前决策就是拿或不拿,以前的最优情况
l[a][b-arr[a]]l[a-1][b]已经有了。不用管的。结合当前状态的定义,就明白了。

至此,时间优化到严格o(a*b),空间o(a*b),空间还能优化到o(min(a,b)),下一个题讲压缩方法。

第二个萌新题

给一个由数字组成的矩阵,初始在左上角,要求每次只能向下或向右移动,路径和就是经过的数字全部加起来,求可能的最小路径和。

1  3  5  9

8  1  3  4

5  0  6  1

8  8  4  0

路径:1 3 1 0 6 1 0路径和最小,返回12

生成和矩阵相同大小的二维表DP,用来记录当前的最小路径和

(以后也不分析暴力的时间复杂度了)

对于普遍的位置i,j,只有i-1,j和i,j-1这两个位置可以一步走到这里,所以

DP[i,j]=min(DP[i,j-1],DP[i-1,j])+L[i,j]

压缩:我们发现,除了这个位置上本身的数,DP[i,j]只和DP表中左边和上边的值有关,所以可以生成长度为矩阵较小边长一维表,用两层循环。注意顺序,从左向右打表,只有这样,左边的那个元素才是被更新过的,才是本行的左边那个元素。

最左边的DP值是直接累加的,其他位置

For i 0 to 高度:

    For j 0 to 宽度

DP[j]=min(DP[j-1],DP[j])+L[i,j]

时间不变,空间优化到o(较小边长)

第三道萌新题

题干和第一题一样,请返回所有的还钱方法有多少种

经过一二题,应该自己会做了。

那直接给个py的code,不讲咯。。
简单的,百度拼凑面额。。

 


n=int(input())
dp=[0]*(n+1)
dp[0]=1
tmp=[1,5,10,20,50,100]
for kk in tmp:
    for i in range(kk,n+1):
        dp[i]+=dp[i-kk]
print(dp[n])

好啦,下下次终于可以写点好玩的了。。开心
大佬勿喷哈

有错误赶紧告诉我,谢谢哈

[dp优化]个人对dp优化的理解

动态规划优化 矩阵乘法 单调队列 斜率优化 决策单调性 四边形不等式
  • hbhcy98
  • hbhcy98
  • 2016年02月05日 13:34
  • 2317

DP优化总结

矩阵优化DP 例子 fib数列 fib数列拓展 kmp转移 小型图的转移 决策单调栈优化 例子 玩具装箱Toy 土地购买 单调队列优化DP 例子 单调队列维护决策 单调队列维护可选决策...
  • qq_35649707
  • qq_35649707
  • 2017年09月05日 08:32
  • 463

uva11584(暴力DP)

题意: 给出一个串,把它切成尽量少的串,使每个串都是回文; 思路: dp[i]表示前i个字符最少能划分成几个串; 枚举j 如果j 到 i是一个回文; 那么dp[i] = dp[j -...
  • yeyeyeguoguo
  • yeyeyeguoguo
  • 2015年03月20日 19:37
  • 512

ACM学习感悟——暴力专场E 暴力dp

Problem Description 小晴天:“我有一个数列!” 小晴天:“我还要有很多很多的数列!” 于是小晴天就把这个数列的所有连续子数列写出来。 然后小晴天把每个连续子数列中的最大...
  • CQUWEL
  • CQUWEL
  • 2015年04月18日 11:33
  • 292

从快速幂到dp 优化:矩阵快速幂

幂运算 nn 个aa 相加我们当然不会写成一个循环,nn 个aa 相乘我们自然要用幂运算。 幂运算裸题 题目链接 L1-012. 计算指数 解法 用上cmat...
  • CSDNjiangshan
  • CSDNjiangshan
  • 2017年07月14日 21:05
  • 875

矩阵乘法优化DP

矩阵乘法优化DP 在许多的DP题目中,转移方程本身不难推,但是需要循环的次数巨大。这时候可以利用矩阵乘法将时间复杂度从O(n) 优化到 O(log n)。这里只用十分简单的一维DP做例子。如何乘在矩...
  • u011056504
  • u011056504
  • 2016年06月04日 17:03
  • 1897

【nodejs】新手如何一步步创建一个简单的express项目

1.环境及工具的说明: PC系统:Windows 10; 命令行工具:CMD; 2. 首先,在您的工程目录下,创建一个package.json文件; 文件配置如下:`{ "name": ...
  • u013307254
  • u013307254
  • 2016年10月06日 17:33
  • 94

poj3666(dp前缀优化)

链接:点击打开链接 题意:将A1....An变为B1.....Bn,要求序列B满足非严格单调递增或非严格单调递减,代价为|A1-B1|+|A2-B2|+...+|AN -BN|,输出最小代价 代码: ...
  • stay_accept
  • stay_accept
  • 2016年05月31日 17:35
  • 585

分区表的直白描述

answer: 普通表呢像一个小学生用的新华字典,分区表呢像一套博士们辞海,在同一个漂亮的盒子里面(表名)有若干本辞海分册(每一册就是一个分区了)。    如果说检索一张普通表就像查新化...
  • ningjieshuijing
  • ningjieshuijing
  • 2010年12月01日 16:47
  • 516

HDU 2089 不要62(数位dp/暴力打表)

解题思路: 这题第一次做的时候,因为数据范围小,只有10^6,所以果断选择了暴力打表。在够表的时候,一开始少了a[i/10]==1这个条件,算出来的值总是多,, 然后加上后,扫一遍就过。 先看看...
  • wikioi_bai
  • wikioi_bai
  • 2015年02月20日 11:51
  • 451
收藏助手
不良信息举报
您举报文章:简单暴力到dp的优化(入门篇)
举报原因:
原因补充:

(最多只允许输入30个字)