动态规划算法一直是我最恐惧的算法,因为大学里整了一年也没明白这个算法,导致和很多机会失之交臂。工作多年来也没敢再去碰,今天花了点时间再看了下,也算了却自己的一桩心愿。
需要解决的问题是寻找最长递增子序列,ACM里面这个问题衍生了无数题目,万变不离其宗,很多题目连代码都一样。
有一个序列,比如3,5,1,4,8,6 最长递增子序列就是从中找一串数字,顺序不能变,可以跳着找,找到最长的那串。比如3,5,8是一串递增子序列,1,4,6也是递增子序列。这个例子中最长的有多个,长度为3.
这题目可以用动态规划来解决。首先我们考虑只有一个值的数字串,比如3,它的最长子序列就是1了,再在这个数字串中加5,变成3,5数字串,由于5>3,意味着以5结尾的字符串长度不会比以3结尾的字符串长度小,所以最长子序列为(以3结尾的字符串长度)L(0)+1,,当数字串变成3,5,1时,由于1<3且1<5,所以1不能和任何之前的数字组成序列,所以1值的子序列为1 。当数字串为3,5,1,4时,我们知道3<4,意味着以4为结尾的字符串长度不会比以3为结尾的字符串长度小,则在以3为结尾的字符串长度L(0)上加1,以3为结尾的字符串长度为1,则以4为结尾的字符串长度最少为2 。以此类推。示例如下:
下标: L(0) L(1) L(2) L(3) L(4) L(5)
值: 3 5 1 4 8 6
最大长度: 1 2 1 2 3 3
L(0)+1 L(0)+1 L(1)+1 L(1)+1
代码如下:
#include<iostream>
using namespace std;
int main()
{
int arr[]={5,7,3,9,4,1,8,11,13,18,15};
int longest[11]={1};
for( int j=1; j<11; j++)
for( int i=0; i<j; i++)
{
if( arr[j]>arr[i] && longest[j]<longest[i]+1 )
longest[j]=longest[i]+1;
}
int maxNum=0;
for( int i=0; i<11; i++ )
{
if( maxNum < longest[i] )
maxNum=longest[i];
}
cout<<maxNum<<endl;
}