最长上升子序列

来源:互联网 发布:淘宝化妆品小样靠谱点 编辑:程序博客网 时间:2024/06/05 09:57

#include<iostream>using namespace std;int main(){    int n;    cin>>n;    int a[n];    for(int i=0;i<n;i++)    {        cin>>a[i];    }    int m[n];    for(int i=0;i<n;i++)    {        m[i]=0;    }    for(int i=0;i<n;i++)    {        int maxj=0;        for(int j=0;j<i;j++)        {            if(a[i]>a[j]&&m[j]>maxj)            {                maxj=m[j];            }        }        m[i]=maxj+1;    }    int maxn=m[0];    for(int i=1;i<n;i++)    {        if(m[i]>maxn)            maxn=m[i];    }    cout<<maxn<<endl;}

    本题是一道经典的动态规划题目。动态规划是运筹学的一个重要分支,它是解决多阶段决策问题的一种有效的数量化的方法。动态规划是由美国学者贝尔曼等人创立的。1951年贝尔曼首先提出了动态规划中解决多阶段决策问题的最优化原理,并给出了许多实际问题的解法。1957年贝尔曼出版了《动态规划》一书,标志着运筹学这一重要分支的诞生。

    动态规划可以优雅而高效地解决许多用贪心算法或分治算法难以解决的求最优解的问题,而求最优解的问题旺旺看似简单,但程序实现起来很难,往往容易出现重复计算,产生超时错误。

    用动态规划解题,首先要把原问题分解成若干个子问题,这一点与递归方法类似。动态规划与递归的区别在于:单纯的递归往往会导致子问题重复计算,而运用动态规划方法,子问题的解一旦被求出就会被保存,所以,子问题只需求一次。

    本题要求的是最长上升子序列,如何把这个问题分解为子问题呢?经过分析,发现“求以ak(k=1,2,3,...n)为终点的最长上升子序列的长度”是个比较好的子问题。