码迷,mamicode.com
首页 > 其他好文 > 详细

dp概括(1)

时间:2015-08-16 12:27:43      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

本文借鉴网上某视频

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))











版权声明:本文为博主原创文章,未经博主允许不得转载。

dp概括(1)

标签:

原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/47700363

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!