hdoj1423 Greatest Common Increasing Subsequence

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值