最長遞增子序列,最長,進一步要給出一個序列(動態規劃)
阿新 • • 發佈:2018-12-24
牛客網
給定一個長度為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;
}