最长上升子序列LIS

题目:
给你一个长度为n的序列,让你找到最长上升子序列的长度.

分析:

这个是dp的经典问题,今天拿来重新学习一下。

如果按照贪心的想法,是很容易看到有问题的,比如一串数字 1,3,-3,-2,-1;

贪心的话从1开始,依次序列结尾的数字大的数,1,3长度为2,实际上LIS的长度为3

所以不能够用贪心来做,考虑dp。

dp的话,首先应该拆分问题:

要求n个,那么就找n-1个数的,n-2个数字的,找到这些状态之间的联系。

(其实对我来说这样来思考的话,我比较难找到状态方程)

不如从1个数字开始,假设dp[i]为当前数字结尾的序列的lis长度,那么对于前面以a[j]结尾的序列,如果a[i]>a[j],dp[i]=max(dp[j]+1);

这样就找到了转移关系,到这里之后应该注意到,我们只是把每一个数字结尾的lis找了出来,但这不是全局最优解,所以应该再找到最大的dp[i],才是最后的结果。

代码如下:

#include<iostream>
using namespace std;
int a[100001];
int dp[100001];
int main()
{
int i,j,n;
int ans=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
dp[i]=1;
}
for(i=1;i<n;i++)
{
for(j=0;j<i;j++)
{
if(a[j]<a[i])
{
dp[i]=max(dp[i],dp[j]+1);
}
}
ans=max(ans,dp[i]);//一边计算dp[i]一边求出了最大dp[i]
}
cout<<ans<<endl;

 

return 0;
}

对于求最优解问题来说,先看下能不能贪心,不能,用dp.

对于dp问题,最重要的是拆分问题,问题怎么拆?我们假设什么量来表示,这个应该是解决问题的关键吧。

posted @ 2018-02-09 18:15  zero1998  阅读(116)  评论(0编辑  收藏  举报