前言:我們先了解一下最長連續遞增子序列的求解!
#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;//最長子序列的個數
}