hdoj1423 Greatest Common Increasing Subsequence
时空限制 1000ms/64MB
【问题描述】
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequenc
【输入格式】
Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
【输出格式】
output print L - the length of the greatest common increasing subsequence of both sequences.
【样例输入】
1
5
1 4 2 5 -12
4
-12 1 2 4
【样例输出】
2
【代码】
f[i][j]表示以数组a的前i个元素与数组b的前j个元素且以b[j]为结尾构成的LCIS的长度
f[i][j] = f[i-1][j] (a[i] != b[j])
f[i][j] = max(f[i-1][k]+1) (1 <= k < j && b[j] > b[k]) (a[i]==b[j])
法一:O(n^3) 空间n^2
#include<iostream> //O(n^3)
#include<algorithm>
using namespace std;
const int N = 505;
int T,n,m,a[N],b[N],f[N][N];
int main(){
cin>>T;
while (T--){
cin>>n;
for (int i=1; i<=n; i++) cin>>a[i];
cin>>m;
for (int i=1; i<=m; i++) cin>>b[i];
fill(f[0],f[0]+N*N,0);
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
if (b[j]!=a[i]) f[i][j]=f[i-1][j];
else {
for (int k=1; k<j; k++) //找最大值
if (b[k]<b[j]) f[i][j]=max(f[i][j],f[i-1][k]);
f[i][j]++; //接上b[j]
}
int ans=f[n][1];
for (int j=2; j<=m; j++) ans=max(ans,f[n][j]);
cout<<ans<<endl;
if (T) cout<<endl;
}
return 0;
}
法二:O(n^2) 空间n^2
维护一个maxv值来储存最大的f[i-1][k]值。即只要有b[j]<a[i]的地方,那么我们就可以更新最大值,所以,当a[i] == b[j]的时候,f[i][j] = maxv+1。
#include<iostream> //O(n^2)
#include<algorithm>
using namespace std;
const int N = 505;
int T,n,m,a[N],b[N],f[N][N];
int main(){
cin>>T;
while (T--){
cin>>n;
for (int i=1; i<=n; i++) cin>>a[i];
cin>>m;
for (int i=1; i<=m; i++) cin>>b[i];
fill(f[0],f[0]+N*N,0);
for (int i=1; i<=n; i++){
int maxv=0;
for (int j=1; j<=m; j++){
if (b[j]<a[i]) maxv=max(maxv,f[i-1][j]); //更新时,找最大值
if (b[j]!=a[i]) f[i][j]=f[i-1][j];
else f[i][j]=maxv+1; //接上b[j]
}
}
int ans=f[n][1];
for (int j=2; j<=m; j++) ans=max(ans,f[n][j]);
cout<<ans<<endl;
if (T) cout<<endl;
}
return 0;
}
法三:O(n^3) 空间n
上面的代码有些地方与0/1背包很相似,即每次用到的只是上一层循环用到的值,即f[i-1][j],那么我们可以像优化0/1背包问题利用滚动数组来优化空间。
#include<iostream> //O(n^2) 空间优化O(n)
#include<algorithm>
using namespace std;
const int N = 505;
int T,n,m,a[N],b[N],f[N];
int main(){
cin>>T;
while (T--){
cin>>n;
for (int i=1; i<=n; i++) cin>>a[i];
cin>>m;
for (int i=1; i<=m; i++) cin>>b[i];
fill(f,f+N,0);
for (int i=1; i<=n; i++){
int maxv=0;
for (int j=1; j<=m; j++){
if (b[j]<a[i]) maxv=max(maxv,f[j]); //更新时,找最大值
if (b[j]==a[i]) f[j]=maxv+1; //接上b[j]
}
}
int ans=f[1];
for (int j=2; j<=m; j++) ans=max(ans,f[j]);
cout<<ans<<endl;
if (T) cout<<endl;
}
return 0;
}