求最长递增子序列长度
要求
-
输入一个数组a,求它的最长单调递增子序列
解题
-
- 动态规划dp数组完美解决
- dp[i]:以a[i]结尾的最长递增子序列的长度。
- 初始化:dp[i]=1
- 状态转移方程:dp[i] = max( dp[0…i-1] +1, dp[i] ).
- 解释:对于dp[i],求a[i]结尾的最长递增子序列,在a[0..i-1]中选出比a[i]小且长度最长的dp[j] ;如果所有的 dp[0…i-1] +1都比 dp[i] 小,则 dp[i]=1;
#include<iostream>
using namespace std;
const int N = 102;
int n;
int a[N];
int dp[N];
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
int max_lis = 0;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i] = 1;
for(int j=i-1;j>=1;j--){
if(a[i]>a[j]){
dp[i] = max(dp[i],dp[j]+1);
}
}
max_lis = max(dp[i],max_lis);
}
cout<<max_lis<<endl;
}
return 0;
}
求最长递增子序列长度并输出第一个最长的递增子序列
要求
-
输入一个数组a,求它的最长单调递增子序列,并且输出第一个最长的递增子序列
解题
-
- 在求最长子序列长度的基础上,增加一些操作完成下标的记录
- 最后使用递归输出每一个元素
- 解释:
对于输入样例:
1
10
4 1 5 2 9 1 28 17 31 90
a[i] | 4 | 1 | 5 | 2 | 9 | 1 | 28 | 17 | 31 | 90 |
---|
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
dp[i] | 1 | 1 | 2 | 2 | 3 | 1 | 4 | 4 | 5 | 6 |
pre[i] | 1 | 2 | 1 | 2 | 3 | 6 | 5 | 5 | 8 | 9 |
-
所以最长长度为6,递归输出序列为 1 2 9 17 31 90
#include<iostream>
using namespace std;
const int N = 102;
int n;
int a[N];
int pre[N];
int dp[N];
void print(int index){
if(pre[index]==index){
cout<<a[index];
return;
}
print(pre[index]);
cout<<" "<<a[index];
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
int max_lis = 0;
int index=1;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i] = 1;
pre[i] = i;
for(int j=i-1;j>=1;j--){
if(a[i]>a[j]){
if(dp[i]<dp[j]+1){
dp[i] = dp[j]+1;
pre[i] = j;
}
}
}
if(dp[i]>max_lis){
max_lis = dp[i];
index = i;
}
}
cout<<max_lis<<endl;
print(index);
printf("\n");
}
return 0;
}