1. 程式人生 > >最長遞增子序列,最長,進一步要給出一個序列(動態規劃)

最長遞增子序列,最長,進一步要給出一個序列(動態規劃)

牛客網

給定一個長度為N的陣列,找出一個最長的單調自增子序列(不一定連續,但是順序不能亂)
例如:給定一個長度為8的陣列A{1,3,5,2,4,6,7,8},則其最長的單調遞增子序列為{1,2,4,6,7,8},長度為6.

輸入描述

第一行包含一個整數T,代表測試資料組數。

對於每組測試資料:

N-陣列的長度

a1 a2 ... an (需要計算的陣列)

保證:

1<=N<=3000,0<=ai<=MAX_INT.

輸出描述

對於每組資料,輸出一個整數序列,代表最長遞增子序列。

若有多組最長上升子序列,輸出第一組。

保證:1<=T<=20,1<=N<=3000,0<=ai<=MAX_INT.

輸入樣例

2
7
89 256 78 1 46 78 8
5
6 4 8 2 17

輸出樣例

1 46 78
6 8 17
  • ac程式碼
#include <cstdio>  
#include <cstdlib>  
#include <cstring>    
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <iostream>
#include <queue>
#include <map> #include <set> #include <stack> #include <list> #include <sstream> #include <algorithm> using namespace std; const int INF = 0x7fffffff; const int N = 100005; int main() { //freopen("in.txt", "r", stdin); int t; scanf("%d", &t); while
(t--) { int n; scanf("%d", &n); vector<int> v; for (int i = 0; i < n; i++) { int tmp; scanf("%d", &tmp); v.push_back(tmp); } vector<int> dp(n,1); // dp[i] 表示 以v[i]結尾且能構成最長遞增序列的長度 vector<int> pre(n,-1); int maxLen = 1; int lastpos; for (int i = 0; i < n;i++) { // 對於dp[i], 可以通過 dp[0] 到 dp[i-1] 求解出來 for (int j = 0; j < i; j++) { if (v[j] < v[i]) { if (dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; pre[i] = j; } } if (dp[i] > maxLen) { maxLen = dp[i]; lastpos = i; } } } vector<int> ans; while (lastpos != -1) { ans.push_back(v[lastpos]); lastpos = pre[lastpos]; } //cout << maxLen << endl; for (int i = maxLen - 1; i > 0; i--) cout << ans[i] << " "; cout << ans[0] << endl; } return 0; }