寒假复习笔记——动态规划篇&poj3124

概念:

动态规划与很多算法一样,其初始思想是很简单的:把程序运行过程中已经算出来的,而且以后可以用到的信息记录下来,以后再用的时候只需要查表即可。

我最开始见到的动态规划的最简单例子是求斐波那契数列:

递归:

Int f(int  i){

   If(i==0||i==1)return 1;

   Return f(i-1)+f(i-2);

}

动态规划:

Int f[];f[0]=1;f[1]=1;

For(int i=2;i<?;i++)

    F[i]=f[i-1]+f[i-2];

容易看出来动态规划复杂度是线性的,递归的复杂度是指数级的//当然求解该数列还有一些//基于奇奇怪怪的数学结论的奇奇怪怪但是很高效的算法,不赘述

这里第二个算法之所以高效的原因很明显,就是减少了大量的重复运算。

关于动态规划另一个入门级例题是最长递增子序列(LCS),问题描述如下:

有一个int型的数列,希望找到它的一个子序列,满足如下条件:

1.  该子序列是递增的。

2.  该子序列是递增子序列中最长的。

例如:1 2 3 2 1 4 5 6 3 7  最长递增子序列为    1,2,3,4,5,6,7(子序列不一定在原序列中连续)//这个问题的一个较好的解法是O(NlogN)的,后面会         //详细解释。

额。。还有一个不得不提的重要例子就是   求无向图中所有点对间的最短距离的floyd_warshall算法也是基于动态规划思想的。

稍深入的思考:

稍微想一下,可以发现几个问题:

1.  什么样的数据是以后可用的?

2.  怎样描述这些数据?

3.  怎么用   以前计算出来的这些记录下来了的数据  来推知以后需要的数据?

 

这几个问题前人做过一些回答,我就照搬过来:

答一:把这个问题换一下形势:什么样的问题能够用动态规划?

      拥有最优子结构的问题,多阶段决策的问题。

答二:这个没有明确的答案,简单来说就是抓住数据的几个关键变量。数据的描述又叫状态描述,是个很灵活的东西,后面有几道题目可以稍微体现一下这一方面。

答三:更为“专业”点的说法这个叫做状态转移,状态转移中至关重要的是状态转移方程。

      与状态转移方程一样,这个也很灵活。

 

 

总的来说,这三个问题回答了跟没回答一样。。。虽然说能够稍微帮助一下理解动态规划的要素,造成这个的原因就是木有练习。。。^^

 

另外,值得一提的是,动态规划与贪心一样,并不是所有的问题都能用动态规划的思想解决的,而且,更为直观的,它通常只在一些比较理想的模型上才凑效,比如:线性模型,区间模型,矩阵模型,区间模型,树模型等等。更为一般的模型,例如:无向图模型  通常是不能用动态规划的思路解决的,当然偶尔也可以用。

 

例一:最长递增子序列:LCS

解法:设原数列是A[]

状态描述:Len[i]表示   A[i]及其之前的元素所能构成的最长序列。

          Last[i]表示  A[i]及其之前的元素在最长子序列的条件下的最后一个元素的值

状态转移:Len[i+1]=max{len[k]+1//if(A[i+1]>Last[k])

Len[k]//if(A[i+1]<=last[k])}  其中,k<i+1

如果用了binary_search的话,复杂度便可降低至O(NlogN)

这个算法之所以成功,原因就是我们发现了这个问题所关心的性质,即Len[i]和last[i]

 

上面所提到的问题都还很简单,但是并不是所有的dynamic programming都这么容易想。

例二poj3124

问题描述:

Description

No wonder the old bookcase caved under the massive piles of books Tom had stacked
on it. He had better build a new one, this time large enough to hold all of his books. Tomfinds it practical to have the books close at hand when he works at his desk. Therefore, he is imagining a compact solution with the bookcase standing on the back of the desk. Obviously, this would put some restrictions on the size of the bookcase, it should preferably be as small as possible. In addition, Tom would like the bookcase to have exactly three shelves for aesthetical reasons.

Wondering how small his bookcase could be, he models the problem as follows. He measures the height hi and thickness ti of each book i and he seeks a partition of the books in three non-empty sets S1, S2, S3 such that is minimized, i.e. the area of the bookcase as seen when standing in front of it (the depth needed is obviously the largest width of all his books, regardless of the partition). Note that this formula does not give the exact area of the bookcase, since the actual shelves cause a small additional height, and the sides cause a small additional width. For simplicity, we will ignore this small discrepancy.

Thinking a moment on the problem, Tom realizes he will need a computer program to do the job.

Input

The input begins with a positive number on a line of its own telling the number of test cases (at most 20). For each test case there is one line containing a single positive integer N, 3 ≤ N ≤ 70 giving the number of books. Then N lines follow each containing two positive integers hi, ti, satisfying 150 ≤ hi ≤ 300 and 5 ≤ ti ≤ 30, the height and thickness of book i respectively, in millimeters.

Output

For each test case, output one line containing the minimum area (height times width) of a three-shelf bookcase capable of holding all the books, expressed in square millimeters.

Sample Input

2

4

220 29

195 20

200 9

180 30

6

256 20

255 30

254 15

253 20

252 15

251 9

Sample Output

18000

29796

 

 

问题分析:乍一看,如果枚举所有的可能组合,复杂度为指数级的。。。

          如果把它硬往动态规划上套,可以得到一个稍好一点的动态规划解法,如下:

          用dp[i][h1][t1][h2][t2]表示扫描到第i块时,

第一层高度h1,宽度t1,

第二层高度h2,宽度h2时第三层的最小高度,(第三层的宽度可以算出来)

简单分析一下,这种算法的复杂度为O(N*H^2*T^2),大概是100亿级的计算量。。。。orz。。。

太慢了。^^

算法加速的关键是找到问题的特殊性质。

首先考虑一下我们关心的是问题的哪些方面:

1.  某一层的总宽度

2.  某一层最高的书的高度.

    这也就表明了,我们要知道书架最小面积,并不需要知道每一层具体摆的是哪几本书,而只需要知道每一层的总宽度宽度和每一层最高的那本书的高度。

    但是事实上,上面第一种动态规划的做法也只关心这两个因素。

但是,它有一个很重要的东西没有注意到!!即,书的高度的“序”!!

不过要用到这个性质并不是那么容易的。

那么不妨我们先把书按照高度从小到大排个序(因为这样起码不会让问题变得更复杂)

得到数组book[n](book[n]的数据类型有两个数据成员   height和thickness)。

这样我们瞬间便可发现如果 从  第i到第n本书在同一层,第i-1本书在另一层,那么

第1到i-2本书放在哪一层并不影响这两层中最高的书的高度。

顺着这个稍微想一下便可得到一个较优秀的动态规划算法。

 

 

dp[i][t1][t2]表示  第i到第n本书在第一层,第i-1本书在第一层,且第一层当前宽度为t1,第二层当前宽度是t2时第三层的最小最高高度。

顺着这个思路可以得到一个O(N*T^2)的算法,也就是百万计算量,可以接受了

转载于:https://www.cnblogs.com/njuzyc/archive/2012/01/30/2332357.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值