zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans); if (T) puts("");
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    cf 811c Vladik and Memorable Trip
    Codeforces 837D--Round Subset (DP)
    codeforces798C
    Codeforces 814C
    CodeForces 610D Vika and Segments
    CodeForces 593D Happy Tree Party
    hdu 5564 Clarke and digits
    hdu 5517 Triple
    codeforces 584E Anton and Ira [想法题]
    codeforces 582A GCD Table
  • 原文地址:https://www.cnblogs.com/mmlz/p/6345400.html
Copyright © 2011-2022 走看看