Hdu1423 Greatest Common Increasing Subsequence

Description

This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.

Input

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

output print \(L\) - the length of the greatest common increasing subsequence of both sequences.

Sample Input

1

5
1 4 2 5 -12
4
-12 1 2 4

Sample Output

2

做法一:复杂度\(O(N^3)\)
我们用\(f_{i,j}\)表示\(A\)数组前\(i\)位,B数组前\(j\)位的最长公共上升子串有多长,但是只有\(A_i = B_j\)的时候有意义。dp方程不难想,但是仔细一算复杂度这是\(O(n^4)\)的,为此我们需要加上一些优化。
我们先枚举\(i\),我们可以维护一个数组\(P\)。其中$$P_j = \max { f_{k,j} },k < i$$
然后dp方程就可以变成$$f_{i,j} = \max{ P_k+1 },k < j ; and ; B_k < B_j$$
\(P\)每次dp一个\(i\)都可以\(O(N)\)维护出来。

做法二:复杂度\(O(N^2)\)
\(g_{i,j} = \max \{ f_{k,j},k \le i \}\),然后我们想想怎么用\(g\)直接来dp。
\(ma = \max \{ f_{i-1,k},k < j \; and \; A_i > B_k \}\)
首先$$g_{i,j} = g_{i-1,j}$$
然后若\(A_i = B_j\),则$$g_{i,j} = \max{ g_{i,j},ma+1 }$$
最后$$ans = \max { g_{N,i} },1 \le i \le M$$
代码1:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

const int maxn = 510,inf = 1<<30;
int f[maxn][maxn],A[maxn],B[maxn],P[maxn],T,N,M,ans;

int main()
{
	freopen("1423.in","r",stdin);
	freopen("1423.out","w",stdout);
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d",&N); ++N; A[1] = 0;
		for (int i = 2;i <= N;++i) scanf("%d",A+i);
		scanf("%d",&M); ++M; B[1] = 0;
		for (int i = 2;i <= M;++i) scanf("%d",B+i);
		for (int i = 1;i <= N;++i) for (int j = 1;j <= M;++j) f[i][j] = -inf;
		for (int i = 1;i <= M;++i) P[i] = -inf;
		ans = f[1][1] = P[1] =0;
		for (int i = 2;i <= N;++i)
		{
			for (int j = 2;j <= M;++j)
			{
				if (A[i] != B[j]) continue;
				for (int k = 1;k < j;++k) if (B[k] < A[i]) f[i][j] = max(f[i][j],P[k]+1);
				ans = max(ans,f[i][j]);
			}
			for (int j = 2;j <= M;++j) P[j] = max(P[j],f[i][j]);
		}
		printf("%d\n",ans); if (T) puts("");
	}
	fclose(stdin); fclose(stdout);
	return 0;
}

代码2:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

const int maxn = 510,inf = 1<<30;
int f[maxn][maxn],A[maxn],B[maxn],P[maxn],T,N,M,ans;

int main()
{
	freopen("1423.in","r",stdin);
	freopen("1423.out","w",stdout);
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d",&N); ++N; A[1] = 0;
		for (int i = 2;i <= N;++i) scanf("%d",A+i);
		scanf("%d",&M); ++M; B[1] = 0;
		for (int i = 2;i <= M;++i) scanf("%d",B+i);
		for (int i = 1;i <= N;++i) for (int j = 1;j <= M;++j) f[i][j] = -inf;
		for (int i = 1;i <= M;++i) P[i] = -inf;
		ans = f[1][1] = P[1] =0;
		for (int i = 2;i <= N;++i)
			for (int j = 2,ma = 0;j <= M;++j)
			{
				f[i][j] = f[i-1][j];
				if (A[i] == B[j]) f[i][j] = ma+1;
				if (A[i] > B[j]&&ma < f[i-1][j]) ma = f[i-1][j];
			}
		for (int i = 1;i <= M;++i) ans = max(ans,f[N][i]);
		printf("%d\n",ans); if (T) puts("");
	}
	fclose(stdin); fclose(stdout);
	return 0;
}
posted @ 2017-01-24 00:12  lmxyy  阅读(132)  评论(1编辑  收藏  举报