dp概括(1)

本文借鉴网上某视频

Dynamic programming(动态规划)

1、将一个问题分解成许多子问题进行求解,最后再由子问题答案得到原本问题的答案(类似分治法)

2、相同的子问题会出现不止一次(与分治法区别)

3、将子问题的答案记录下来(可用记忆化搜索,以空间换时间)


问题一:用1*2的骨牌填满2*n的格子,共有多少种排法?
solve:以f(n)表示填满2*n格子的方法数,观察最后一格放置骨牌的情形


状态转移方程:f(n)=f(n-1)+f(n-2)
初始条件:f(1)=1,f(2)=2

费氏数列(斐波那契序列)

代码:1、自顶向下(一般采用递归);2、自底向上(一般采用循环)


问题二:将n个排成一列的格子涂上红、绿、蓝三种颜色,且蓝绿不可相邻,问有几种涂法?

solve1:设f(n)为涂n格的方法数,但f(n)=???,状态转移方程不知道怎么写?

solve2:

设f(n,0)为涂n格,且最后一个为红色的方法数

设f(n,1)为涂n格,且最后一个为绿色的方法数

设f(n,2)为涂n格,且最后一个为蓝色的方法数

状态转移方程:

f(n,0)=f(n-1,0)+f(n-1,1)+f(n-1,2)

f(n,1)=f(n-1,0)+f(n-1,1)

f(n,2)=f(n-1,0)+f(n-1,2)

初始条件:f(1,0)=f(1,1)=f(1,2)=1


状态:用一些数字可以唯一的表示一个子问题

状态转移:如何由其他状态转移到某个状态

定义状态时应该注意的事

1、状态不能太多?(太多数组开不下,考虑状态压缩)

2、能否导出状态转移方程?(如问题2中,刚开始使用一维的状态很难导出状态的转移方程,所以我们重新定义状态为二维)

定义出状态且能导出状态转移方程

1、时间复杂度是否合理?

2、若不合理,能不能对状态转移方程做出优化?(如问题三,还有矩阵幂运算等等)

3、若还是不行,试试用其他方法定义状态

如何找出正确的状态转移方程呢?

1、靠经验

2、靠灵感


问题三:用1*2和1*3的L型骨牌填满2*n格子,共有几种排法?

定义状态:f(n)表示填满2*n格子的方法数(判断状态是否太大)

状态转移:

同样考虑最后一格的方法,放1*2的case已经在问题1中讨论过,因此只讨论放L型骨牌的case




    

·

·

·


分析:因为上面的良好总情况是对称的,所以只考虑一种方向

最后放1*2: f(n-1)+f(n-2)

最后放L型: 2[f(n-3)+f(n-4)+···+f(1)+f(0)]

状态转移方程:

f(n)=f(n-1)+f(n-2)+2[f(n-3)+f(n-4)+···+f(1)+f(0)]     O(n)的时间转移

优化f(n)=f(n-1)+f(n-2)+2[f(n-3)+f(n-4)+···+f(1)+f(0)]

方法一:使用变数记录前缀和:tmp=f(0)+f(1)+···+f(n-3)

如此状态转移变成:f(n)=f(n-1)+f(n-2)+2*tmp       O(1)的时间转移

方法二:化简转移式

f(n-1)=f(n-2)+f(n-3)+2[f(n-4)+f(n-5)+···+f(1)+f(0)]

f(n-1)+f(n-3)=f(n-2)+2[f(n-3)+f(n-4)+···+f(1)+f(0)]

得到2[f(n-3)+f(n-4)+···+f(1)+f(0)]=f(n-1)-f(n-2)+f(n-3)

转移式变成f(n)=2f(n-1)+f(n-3)                                 O(1)的时间转移


方法二:
f(n,0):铺满2*n的方法数
f(n,1):铺满2*n且下面多一格的方法数
状态转移:
f(n,0)=f(n-1,0)+f(n-2,0)+2f(n-2,1)
f(n,1)=f(n-1,0)+f(n-1,1)
初始状态:
f(0,0)=1,f(0,1)=0
f(1,0)=1,f(1,1)=1
f(2,0)=2,f(2,1)=2

问题四:给一个正整数,现在从里面取出一些数,但两数不能相邻,求取出数字和的最大值?

方法一:
定义状态:f(n)为从arr[1]到arr[n]中取数字,且取到arr[n]的总和最大值
状态转移:f(n)=max(f(n-2),f(n-3))+arr[n]
最后答案:max(f(n),f(n-1))

方法二:
定义状态:
f(n,0)为从f(n)为从arr[1]到arr[n]中取数字,且没有取到arr[n]的总和最大值
f(n,1)为从f(n)为从arr[1]到arr[n]中取数字,且有取到arr[n]的总和最大值
状态转移:
f(n,0)=max(f(n-1,0),f(n-1,1))
f(n,1)=f(n-1,0)+arr[n]
最后答案:max(f(n,0),f(n,1))











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值