最長上升子序列又名最長不下降子序列,英文名Longest Increasing Subsequence(簡稱LIS)
What is LIS?
首先介紹一下子序列吧。子序列就是一組數據中的一些數據組成的序列(說實話我也解釋不清QAQ!!)
舉個栗子吧:
我們有一組數據:21 56 13 57 96 31 52
那么,21 13 96是它的子序列;56 13 96 52也是它的子序列
就是說只要保證原數據的順序不變,子序列中的數據在原數據中不一定要相鄰。
那么,上升子序列又是什么呢?
顧名思義,上升嘛,就是從小到大排列。
像我舉的例子中的一組上升子序列是:21 56 57 96
這樣你們明白了嗎?
現在給出了數據的長度n,並且給出了具體數據,讓你求它的最長的上升子序列的長度是多少。
也許會有多個解,但是題目只要求你求出長度,那么這個多解就沒必要考慮了。
如果沒學過DP,那么我么第一時間想到的是貪心;
那么,像這樣一組數據:13,7,9,16,38,24,37,18,44,19,21,22,63,15
按照貪心的話,求出的應該是13,16,18,19,21,22,63這樣一個長度為7的上升子序列
但是,實際上,7 ,9,16,18,19,21,22,63——長度為8,才是正解。
既然有反例了,那么我們就否認貪心。
那怎么辦?暴力?枚舉?
可以!
但是如果數據太大,那就會TLE了。。。QWQ!
實在不行,我們就請出我們的DP大法!
首先我們日常定義dp[i],表示以第i個數據為結尾的最長上升子序列的長度
我們假設以第j號數據為尾的最長上升子序列的長度為a,如果現在的這個數據i要大於j的話,那么i的最長上升子序列就不需要從最前面算了,就直接是j的最長上升子序列長度+1
#include<bits/stdc++.h> using namespace std; int n;//數據的長度 int num[10010];//用於存儲數據 int dp[10010]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>num[i]; } dp[0]=1;//第0號元素默認為1 int ans=-1; for(int i=1;i<=n;i++) { dp[i]=1;//每一個數的初始子序列的長度必定為1,因為有他自己存在 for(int j=1;j<i;j++)//j從1開始循環至i-1 { if(num[i]>num[j])//如果符合上升的條件 {
dp[i]=max(dp[i],dp[j]+1)//那么i的上升子序列長度就是j的上升子序列的長度+1
} } ans=max(ans,dp[i]);//維護答案最大 } cout<<"max="<<ans<<endl; return 0; }
