1,先离散化,然后DP:
注意这个解法中,dp[i][j][k]代表a序列中前i个和b序列中前j个数结尾为k或小于k时的最大。
但是由于i是单增(一次1->n),而j反复变化(多次1->m),因此i可以滚动,而j不可以。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int x[501],y[501],xx[501],yy[501],dp[2][501][1001];
int tmp[1002],cnt,m,n,Max;
map<int,int>q;
void _lisan()
{
int i,j;
q.clear();
cnt=0;
scanf("%d",&n);
for(i=1;i<=n;i++) {
scanf("%d",&x[i]);
tmp[i]=x[i];
}
scanf("%d",&m);
for(i=1;i<=m;i++) {
scanf("%d",&y[i]);
tmp[n+i]=y[i];
}
sort(tmp+1,tmp+m+n+1);
q[tmp[1]]=++cnt;
for(i=2;i<=m+n;i++)
if(tmp[i]!=tmp[i-1]) q[tmp[i]]=++cnt;
for(i=1;i<=n;i++)xx[i]=q[x[i]];
for(i=1;i<=m;i++)yy[i]=q[y[i]];
memset(dp,0,sizeof(dp));
Max=0;
}
int main()
{
int T,i,j,k;
cin>>T;
while(T--){
_lisan();
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(xx[i]==yy[j]){
dp[i%2][j][xx[i]]=max(dp[i%2][j][xx[i]],dp[(i+1)%2][j-1][xx[i]-1]+1);
}
for(k=0;k<=cnt;k++)
{
dp[i%2][j][k]=max(dp[i%2][j][k],dp[(i+1)%2][j][k]);
dp[i%2][j][k]=max(dp[i%2][j][k],dp[i%2][j][k-1]);
dp[i%2][j][k]=max(dp[i%2][j][k],dp[i%2][j-1][k]);
}
}
printf("%d
",dp[n%2][m][cnt]);
if(T)printf("
");
}
return 0;
}
2, LCIS套模板:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define maxn 1000+5
using namespace std;
int a[maxn],b[maxn];
int f[maxn];
int n,m;
int LCIS()
{
int ans=0;
for(int i=1;i<=n;i++){
int tmp=0;
for(int j=1;j<=m;j++){
if(a[i]==b[j]) f[j]=tmp+1;
else if(a[i]>b[j]){
if(tmp<f[j])
tmp=f[j];
}
}
}
for(int i=1;i<=m;i++)
ans=max(ans,f[i]);
return ans;
}
int main()
{
int T;
cin>>T;
while(T--){
memset(f,0,sizeof(f)) ;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
printf("%d
",LCIS());
if(T)printf("
");
}
}