最长递增子序列

来源:互联网 发布:js怎么给文本框赋值 编辑:程序博客网 时间:2024/06/07 15:29

最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点。
在一个已知的序列 {a1,a2,...an} 中,取出若干数组成新的序列{ai1,ai2,...aim} , 其中下标i1i2im保持递增,即新数列中的各个数之间依旧保持原数列中的 先后顺序,那么我们称新的序列{ai1,ai2,...aim}为原序列的一个子序列。
若在子序 列中,当下标ix>iy 时,aix>aiy ,那么我们称这个子序列为原序列的一个递增 子序列。最长递增子序列问题,就是在一个给定的原序列中,求得其最长递增子 序列长度。
有序列 {a1,a2,...an},我们求其最长递增子序列长度。按照递推求解的思想, 我们用 F[i]代表若递增子序列以 ai 结束时它的最长长度。当 i 较小,我们容易直 接得出其值,如 F[1] = 1。那么,如何由已经求得的 F[i]值推得后面的值呢?
假设,F[1]到 F[x1]的值都已经确定,注意到,以 ax结尾的递增子序列,除了长度 为 1 的情况,其它情况中,ax都是紧跟在一个由 ai(i<x)组成递增子序列之后。要 求以 ax 结尾的最长递增子序列长度,我们依次比较 ax 与其之前所有的 ai(i<x), 若 ai小于ax,则说明 ax可以跟在以 ai结尾的递增子序列之后,形成一个新的递 增子序列。又因为以 ai结尾的递增子序列最长长度已经求得,那么在这种情况下, 由以 ai结尾的最长递增子序列再加上 ax得到的新的序列,其长度也可以确定, 取所有这些长度的最大值,我们即能得到 F[x]的值。特殊的,当没有 ai(i<x)小 于 ax, 那 么 以 ax结 尾 的 递 增 子 序 列 最 长 长 度 为 1。即

F[x]=max{1,F[j]+1 | x>j && ax>aj}

我们给出求序列{1,4,3,2,6,5}的最长递增子序列长度的所有 F[i]供读者参考:
这里写图片描述

F[1]=1;
F[2]=max{1, F[1]+1 }=2;
F[3]=max{1, F[j]+1 | aj<a3}=max {1,F[1]+1}=2;
………
【求解最长递增子序列代码如下:】

#include<iostream>using namespace std;int max(int a,int b)///取最大值函数 {    return a>b?a:b;}int main(){    int list[51],n;    int dp[51];///dp[i]保存以第i个数据结尾的最长递增子序列长度    cin>>n;    for(int i=1;i<=n;i++)//录入序列数据    {    cin>>list[i];    }    for(int i=1;i<=n;i++)//按照数组顺序确定每一个dp[i]    {        int tmax=1;//最大值的初始值为1,即以其结尾的最长递增子序列长度至少为1        //f[i]=max {1, f[j]+1|j<i && list[j]<list[i]}        for(int j=1;j<i;j++)//遍历其前所有数据元素         {            if(list[j]<list[i])//若第j个比当前的值要小            tmax=max(1,dp[j]+1);//将当前元素i排列在j号结尾的最长递增子序列之后,计算其长度dp[j] + 1,若大于当前最大值,则更新最大值         }        dp[i]=tmax;    }//求出dp的最大值即可int ans=1;for(int i=1;i<=n;i++){    ans=max(ans,dp[i]);}cout<<ans<<endl;}   
0 0
原创粉丝点击