题目:
题解:
求LCIS
定义状态dp[i][j]表示a[1]~a[i],b[1]~b[j]中,以b[j]结尾的最长公共上升子序列。
流程:
1.a[i]!=b[j],a[i]不能和b[j]匹配,a[i]对答案无贡献,那么 f[i][j]=f[i-1][j];
2.a[i]==b[j],f[i][j]=max(f[i-1][1~j-1])+1;
在循环过程中维护maxx=max(f[i-1][1~j-1]);
对 if(a[i]>b[j]&&maxx<f[i-1][j])maxx=f[i-1][j];
的解释:
由于maxx是在a[i]==b[j]的情况下使用的,且在内层循环中a[i]不变,故a[i]>b[j]中维护的一系列maxx即为f[i-1][1~j-1];
空间复杂度优化:
f[j]的滚动使用,形如01背包
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
const int N=3000+500;
int a[N],b[N];
int f[N][N],n,maxx,ans;
using namespace std;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int j=1;j<=n;j++) scanf("%d",&b[j]);
for(int i=1;i<=n;i++){
maxx=0;
for(int j=1;j<=n;j++){
f[i][j]=f[i-1][j];
if(a[i]>b[j]&&maxx<f[i-1][j])maxx=f[i-1][j];
if(a[i]==b[j]) f[i][j]=maxx+1;
}
}
for(int i=1;i<=n;i++) ans=max(ans,f[n][i]);
printf("%d",ans);
return 0;
}
//风骚的一维打法233
#include<iostream>
#include<cstdio>
#include<algorithm>
const int N=3000+500;
int a[N],b[N];
int f[N],n,maxx,ans;
using namespace std;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int j=1;j<=n;j++) scanf("%d",&b[j]);
for(int i=1;i<=n;i++){
maxx=0;
for(int j=1;j<=n;j++){
if(a[i]>b[j]&&maxx<f[j]) maxx=f[j];
if(a[i]==b[j]) f[j]=maxx+1;
}
}
for(int i=1;i<=n;i++) ans=max(ans,f[i]);
printf("%d",ans);
return 0;
}