1. 程式人生 > >最長上升子序列LIS

最長上升子序列LIS

namespace div 什麽 space 2個 當前 這不 names end

題目:
給你一個長度為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問題,最重要的是拆分問題,問題怎麽拆?我們假設什麽量來表示,這個應該是解決問題的關鍵吧。

最長上升子序列LIS