【算法知识总结】动态规划

看了一些网上讲的内容,先是看看知乎,再看看csdn,最后我看了看百度百科,呵呵。就一个动态规划问题,竟然兜兜转转找了这么多的网址,也是醉了,知乎上的人过于装逼,不好好说话,非得把清晰的问题讲的玄乎,csdn上讲的入门就是直接给你上代码,最后实在无奈,直接百度百科。

动态规划这个东西,听了好多次了,但是真正去了解,也就今天。记得研一上优化方法课的时候,老师给讲线性规划,纯粹了图过的心理。没有详细地把周边知识给整理起来,其实动态规划就是优化方法里面的一个内容。

动态规划,开始我对他的观点就是一个内存存储的分配(简直是傻啊)。其实看完一通,明白,动态规划,说白了就是决策问题,将一个大的问题拆分成好多小问题,然后去解决这些小的问题,然后这些小的问题之间存在着一些联系(这个就是将动态规划问题与分治问题区分的关键)。动态规划问题是为了求到每个子问题的最优,然后寻求到整个问题的最优。动态规划本质上就是优化问题(但是我有一个问题,采用动态规划,是否会陷入到局部最优,就是你看似把每个子问题的最优求到了,但是不一定就是全局最优?存疑!)

由于动态规划的这个性质,因此动态规划会在时间复杂度上有比较大的优势,但是在空间复杂度上存在比较大的问题,因此就相当于拿空间换了时间。

动态规划可以解决的问题也是多种多样的。

 

动态规划一般可分为线性动规,区域动规,树形动规,背包动规四类。

举例:

线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;

区域动规:石子合并, 加分二叉树,统计单词个数,炮兵布阵等;

树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;

背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶(同济ACM第1132题)等;

应用实例:

最短路径问题 ,项目管理,网络流优化等;

可以用到动态规划的地方很多,这次需要总结动态规划的原因,也是因为在牛客网上遇到一道编程题-背包问题。按照网友提供的思路,在百度上搜索背包九讲,可以学会相关的问题,但是可能本人天资愚钝,还是没能明白其中的道理。背包九讲另外一个问题就是纯粹是写作的人的自嗨,其中的思路纯粹是自己跳跃着的,讲的不是很好。

动态规划的本质

动态规划是一种解决问题的思想。这种思想的本质是,一个规模比较大的问题(假如用2-3个参数可以表示),是通过规模比较小的若干问题的结果来得到的(通过取最大,取最小,或者加起来之类的运算)所以我们经常看到的动态规划的核心——状态转移方程都长成这样: 

f[i][j]=f[i-1][j]+f[i][j-1] \\ f[i]=max\lbrace{f[j] & if & j<i and ...} \rbrace+1 \\ f[i][j]=f[0][j-1] && judge(1,i) ||f[1][j-1] && judge(2,i)||...

动态规划的类型

在技术面试中经常出现的是矩阵型,序列型和双序列型。划分型,区间型和背包型偶尔出现。状态压缩和树型基本不会出现(一般在算法竞赛中才会出现)。 

矩阵型:

以矩阵型动态规划为例,一般题目会给你一个矩阵,告诉你有一个小人在上面走动,每次只能向右和向下走,然后问你比如有多少种方案从左上走到右下 (http://www.lintcode.com/problem/unique-paths/)。这种类型状态表示的特点一般是使用坐标作为状态,f[i][j]表示走到(i,j)这个位置的时候,一共有多少种方案。状态的转移则是考虑是从哪儿走到(i,j)这个坐标的

什么样的题适合用动态规划

1. 求最大值/最小值
2. 求可不可行
3. 求方案总数

如果一个问题让你求出“所有的”方案和结果,则肯定不是使用动态规划。 

  • 求出所有具体的方案而非方案个数
  • 输入数据是一个集合而不是序列
  • 暴力算法的复杂度已经是多项式级别
  1. 动态规划擅长优化指数级别复杂度(2^n, n!)到多项式级别复杂度(n^2, n^3)
  2. 不擅长优化n^3到n^2

解决动态规划问题的步骤

1. 状态是什么
2. 状态转移方程是什么
3. 状态的初始值是什么
4. 问题要求的最后答案是什么

序列型:

序列型的动态规划,一般是告诉你一个序列;双序列的动态规划一般是告诉你两个字符串或者两个序列。 

矩阵型动态规划规律总结

1. 确定递归函数意义,或者确定迭代的基本函数式

2. 确定大小范围(矩阵的长宽),设计动态规划矩阵

3. 确定递归终止状态,填表边界(自底向上时,从结尾填表,自顶向下,跟踪递归流程填表)

4. 确定要求的状态(矩阵的值),确定现在要求的状态(矩阵的值与之前一个状态之间的函数关系)

 

《LintCode动态规划题总结》这篇博客讲的很好,很全。值得关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值