动态规划笔记

什么是dp?

dp是英文 dynamic programming,动态的编程。

什么是动态规划?

要了解动态规划,首先需要了解动态规划的两个老前辈:
贪心(Greed): 以当前局部最优的选择来逐步建立一个问题解决方案,最终结果不一定是全局最优解,可以认为是动态规划求解最优化问题的一个特例。

分治(Divide-and-conquer):将问题划分为独立的(independent)子问题,递归地求解子问题(有可能会被反复求解),再将它们的解组合起来,求出原问题的解。

动态规划(Dynamic programming):用分治思想将问题划分为一系列独立的子问题,但各子问题的子子问题重复,即含有重叠的(overlapping)子问题, 则把每个子问题只求解一次(记录在表中),通过组合更小的子问题的解来得到更大子问题的解。

经典再现

用1x2的骨牌填满2n的格子,共有几种填法?
Sol:
以f(n)表示填满2
n格子的方法数
观察最后一格放置骨牌的情形:
在这里插入图片描述

解决方法:
以f(n)表示填满2*n格子的方法数
观察最后一格放置骨牌的情形:
f(n)=f(n-1)+f(n-2)
初始条件:f(1)=1, f(2)=2

问题转化为斐波拉契数列问题  	

这个问题实现方法最简单的就是递归了:
在这里插入图片描述
这是一种非常简便的办法,理解起来也非常简便,但是——它非常的慢。
时间复杂度:O(f(n))= O(2^n)。

原因:重叠子问题
如果把深搜遍历看成是一棵树的话,不难发现问题:
在这里插入图片描述
不只是方框框出来的地方,重复求解的地方数不胜数。

怎么解决,当然是记下来呀!

动态规划的简单优化——拿空间换时间!

将子问题答案记录(Memoization,备忘录)起来,如果递归遇到相同的问题,则直接查表。

时间复杂度:O(n),比起递归算法,是降维打击
DP= Divide and Conquer + Memoization Programming——用表格存储起来,有 “ 以空间换时间”之含义

在这里插入图片描述
搜索树如下:
在这里插入图片描述
红色的部分为直接查表的部分。

在经过动归的初步了解后,现在:

以状态和DAG的观点,重新看待动态规划

动态规划类比
“子问题” = 状态;
全部子问题 = 状态空间;
递推关系 = 状态转移方程;

子问题 = 点;
递推关系 = 边;

在这里插入图片描述

注:图中箭头的意思是要求箭头指到的问题的话,就必须要用到箭头末端的答案。

由图易得,刚才的题还有一种写法:
在这里插入图片描述
因为这个实现方式没有递归调用的开销,表的维护开销也更小,而且,对于某些问题,可以通过改变表的访问模式来进一步降低时空代价,所以目测应该是更优。
但是在动归当中,其实有的状态并不需要一直都保存起,有些子问题的答案用完就可以直接丢弃了,例如这道题,只需要保存上一个和上上个问的答案就可以了。

int fib(int n) 
{   
	 if (n < 2)  return n; 
  	 int prev = 1,curr = 1;  
     for (int  i = 1;  i < n;  i++) {     
        int  sum = prev + curr; 
        prev = curr; 
        curr = sum; 
      }  
   return  curr;
 }

矩阵快速幂优化动态方程求解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值