題目描述一個數列ai如果滿足條件a1 < a2 < ... < aN,那么它是一個有序的上升數列。我們取數列(a1, a2, ..., aN)的任一子序列(ai1, ai2, ..., aiK)使得1 <= i1 < i2 < ... < iK <= N。例如,數列(1, 7, 3, 5, 9, 4, 8)的有序上升子序列,像(1, 7), (3, 4, 8)和許多其他的子序列。在所有的子序列中,最長的上升子序列的長度是4,如(1, 3, 5, 8)。現在你要寫一個程序,從給出的數列中找到它的最長上升子序列。
輸入輸入包含兩行,第一行只有一個整數N(1 <= N <= 1000),表示數列的長度。第二行有N個自然數ai,0 <= ai <= 10000,兩個數之間用空格隔開。輸出輸出只有一行,包含一個整數,表示最長上升子序列的長度。樣例輸入71 7 3 5 9 4 8樣例輸出4
這個題目和最大連續子序列類似,例如有序列A={1,2,3,-1,-2,7,9} (下標從0開始),它的最長不下降子序列是{1,2,3,7,9},長度為5。和之前的分析一樣:
令dp[i]表示以A[i]結尾的最長不下降序列長度 ,從而會有2中情況:
(1)若在A[i]之前存在一個元素A[j](j<i),使得A[i]>=A[j]并且dp[j]+1>dp[i],則可以更新dp[i]=d[j]+1,獲得更長的序列
(2)若在A[i]之前的元素都比A[i]小,A[i]則注定單身一輩子,其序列長度為1
上面的過程可以用下面的小游戲說明,現有一個序列{1,5,2,3},假設我們已經求出以A[0],A[1],A[2]結尾的最長不減序列為{1}、{1,5},{1,2},現在A[3]=3來了:
A[3]:A[0]我可以站在你后面嗎? A[0]:你比我高當然可以!
A[3]:A[1]我可以站在你后面嗎? A[1]:小矮子一邊涼快去!
A[3]:A[2]我可以站在你后面嗎? A[2]:當然可以,我們可以形成更長的遞增序列!
很明顯,在求dp[i]的時候,其會依次和A[j](j<i)比較,只有A[i]較大且d[j]+1>dp[i]才會更新dp[i]的值。因此可以得到如下的狀態轉移方程:
dp[i]=max(1,dp[j]+1) (j=1,2,3..,i-1 && A[j]<A[i])
根據上面的分析,可以給出下面的代碼:
#include<cstdio>#include<algorithm>using namespace std; const int M=1002; int main(){ int n,i,j,a[M],dp[M],ans=1; scanf("%d",&n); for(i=0;i<n;i++){ scanf("%d",a+i); dp[i]=1; } for(i=0;i<n;i++){ for(j=0;j<i;j++){ if(a[i]>=a[j]&&dp[i]<dp[j]+1){ dp[i]=dp[j]+1; } } ans=max(ans,dp[i]); } PRintf("%d/n",ans);}題目來源:http://www.codeup.cn/problem.php?cid=100000627&pid=0
新聞熱點
疑難解答