前言:我们先了解一下最长连续递增子序列的求解!
#include<bits/stdc++.h>
using namespace std;
//求最长连续递增序列
#define maxn 100000
int n,a[maxn],dp[maxn];//dp[i]即前i个元素的上升子序列的长度
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;//初始值设为1
}
int ans=0;
for(int i=1;i<=n;i++){
if(a[i]>a[i-1]) dp[i]=dp[i-1]+1;
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
}
最长上升子序列:求解的这个和上面的求解点不同,我们这个的子序列是可以非连续的。
题目:求最长上升子序列
题目描述:给出一个数列{a1,a2,...,an},要求你选出尽量多的元素,使这些元素按其相对位置单调递增。
任务就是对于给定的序列,求出最长上升子序列的长度。
输入数据:输入的第一行是序列的长度N(1<=N<=1000)。第二行给出序列中的N个整数,这些整数的取值范围都是0~10000。
输出要求:最长上升子序列的长度。
输入样例:
7
1 7 3 5 9 4 8
输出样例:
4
解决方案:DP算法(o(n^2))
dp[i]表示前i个元素的最长上升子序列的长度
决策:第i个元素加到前面哪一个序列k末尾,会使上升子序列的长度最大?
那必然是dp[k]的值越大,dp[i]就越大。
dp[i]=dp[k]+1;其中:1<=k<=i-1 找到dp值最大的k
#include<bits/stdc++.h>
using namespace std;
//求最长递增子序列
#define maxn 100000
int n,a[maxn],dp[maxn];//dp[i]即前i个元素的上升子序列的长度
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;//初始值设为1
}
int ans=0;
for(int i=1;i<=n;i++){//决策:dp[i]=dp[k]+1 找到一个最好的k
for(int j=1;j<i;j++){//找到j始得dp[i]最大
if(a[i]>a[j])
dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
}
求:(最长上升子序列)的个数
讨论:我们这里比前面的更复杂了一点,需要求有多少个最长上升子序列的个数。
#include<bits/stdc++.h>
using namespace std;
//求最长递增子序列
#define maxn 100000
int dp[maxn],a[maxn],ct[maxn],n;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;//初始化为1
ct[i]=1;
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>a[j]){//说明为上升子序列
//dp[i]=max(dp[i],dp[j]+1)
if(dp[i]==(dp[j]+1)){
ct[i]+=ct[j];
}
else if(dp[i]<(dp[j]+1)){
dp[i]=(dp[j]+1);
ct[i]=ct[j];
}
}
}
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
int res=0;
for(int i=1;i<=n;i++){
if(ans==dp[i]){
res+=ct[i];
}
}
cout<<res<<endl;//最长子序列的个数
}