动态规划之LIS

这几天看了不少讲动态规划的书和文章,一般第一个例子就是斐波那契。这个例子真直观,可以将递归发,然后讲自顶向下,自底向上,都没问题。

动态规划还好嘛,not so hard。

但是,从第二个问题开始就不那么直观了。

最喜欢被人用的第二个例子就是这个LIS

Longest increasing sequence.

从一个序列里找出最长的升序子序列的长度:

比如:10,22,9,33,21,50,41,60,80 这个数字序列的最长生升序子序列是10 22 33 50 60 80 , 长度是6。最长升序子序列就是LIS,题目就是要找一个序列的LIS的长度

第一次看的时候以为要找最长子串。后来看了例子才发现不是,子序列里的数不一定在原来的序列里是紧挨着的,只要满足后面比前面大就行。

思路就一层窗户纸。 假设dp[i] = 结尾为i的序列的LIS长度。 那么dp[i+1]是多少呢?那要看第i+1个数字能不能和前面的数字组成新的IS(increasing sequence)。如果能,就在这些IS里面挑个最长(Longest)的。

写个状态转移方程:

dp: f(i)= max(f(j)+1 | 0<j<i && a[i]>=a[j] ) a[i]表示序列里第i个数字的值。

python实现

 1 def lis(a):
 2     l = len(a)
 3     dp = [1 for i in range(l)]   
 4     for i in range(1,l):
 5         for j in range(i):
 6             if a[i] > a[j]:
 7                 dp[i] = max(dp[j]+1,dp[i])
 8     return dp[l-1]            
 9 
10 test = [10,22,9,33,21,50,41,60,80]    
11 print (lis(test))

posted on 2015-02-11 17:36  Gangster  阅读(168)  评论(0编辑  收藏  举报