题目简述
在第一行输入一个数 n n n表示这个序列的字符数,后面输入这 n n n个数。找出最长不下降子序列的长度和这个序列的字符。
题解
这道
L
I
S
LIS
LIS的题目我们选择用动态规划的思路来做,设计一个动态转移方程:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
d
p
[
j
]
+
1
)
.
dp[i]=max(dp[i],dp[j]+1).
dp[i]=max(dp[i],dp[j]+1).这里的
d
p
[
j
]
dp[j]
dp[j]是前面的状态,如果在满足的条件之下,
d
p
[
j
]
+
1
dp[j]+1
dp[j]+1更大,则最大长度取这个值。经历时间复杂度
O
(
n
2
)
O(n^2)
O(n2)的算法后,取出最大上升子序列。
#include<bits/stdc++.h>
using namespace std;
const int N = 1001;
const int inf = 0x7f7f7ff;
int n,a[N],dp[N],len = -inf;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[j]<a[i]){
dp[i] = max(dp[i],dp[j]+1);
}
}
}
for(int i=1;i<=n;i++){
len = max(len,dp[i]);
}
cout<<len<<"\n";
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1001;
const int inf = 0x7f7f7ff;
int n,a[N],dp[N],pre[N],lis[N],len = 0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<=n;i++){
pre[i]=0;
for(int j=1;j<i;j++){
if((a[j]<=a[i])&&(dp[j]>dp[pre[i]])){
pre[i]=j;
}
}
dp[i]=dp[pre[i]]+1;
}
int tail = 0;
for(int i=1;i<=n;i++){
if(dp[tail]<dp[i]) tail = i;
}
while(tail>0){
lis[++len] = tail;
tail = pre[tail];
}
cout<<len<<"\n";
while(len>0){
cout<<a[lis[len]]<<" ";
len--;
}
cout<<endl;
return 0;
}
6
1 6 2 3 7 5
4
1 2 3 7
参考:最长上升子序列 (LIS) 详解+例题模板 (全) 推荐这篇博客哦 !!!