hdu 1423 Greatest Common Increasing Subsequence

来源:互联网 发布:java aes加密算法 编辑:程序博客网 时间:2024/05/21 06:42

Greatest Common Increasing Subsequence

hdu 1423 GCIS (n^2)

省赛的时候,这个题目看了良久,都没想到O(n^2)的算法。后来苏犇看到GCIS的时候就让看模版,然后在吉大的模版上看到了这个

然后我们就顺利的1Y.我又看了一下这个题目,找了好多博客(不是挂了,就是讲的很不清楚)。。然后看到了http://www.tyvj.cn/bbs/Discuss_Show.aspx?id=30583这个博客,博主讲的很给力。

这个题目的状态与LCS的状态差不多,只不过加了些约束dp[i][j]表示a串走到第i个数字,b串走到第j个数字,然后以b串的第j个数字为最终的最长公共递增子序列的长度这样我们就可以直接搞出方程了:

dp[i][j] = dp[i - 1][j] if(a[i] != b[j])
dp[i][j] = max(dp[i - 1][k]) + 1 , 1 <= k < j && b[k] < a[i]

由方程其实我们很容易想到用滚动数组优化,在实现的时候由于在相等的时候b串第j个数字是固定的,所以我们可以很容易的在扫的时候直接计算出对应最大值。。

/*    author    : csuchenan    prog      : hdu 1423    algorithm : Greatest Common Increase Subsequence O(n^2)                dp[i][j] 以b串的j为终点的最长公共上升子序列的长度。                dp[i][j] = dp[i - 1][j] if(a[i] != b[j])                 dp[i][j] = max(dp[i - 1][k]) + 1 , 1 <= k < j && b[k] < a[i]                 由于递推的时候只涉及到i-1,所以我们可以直接用滚动数组优化                详见程序*/#include <cstdio>#include <cstring>const int maxn = 550 ;int dp[maxn] ;int a[maxn]  ;int b[maxn]  ;int GCIS(int la , int lb){    memset(dp , 0 , sizeof(dp)) ;    int i , j , mx ;    for(i = 1 ; i <= la ; i ++){        for(mx = 0 , j = 1 ; j <= lb ; j ++){            if(b[j] < a[i] && mx < dp[j]){                mx = dp[j] ;            }            if(b[j] == a[i]){                dp[j] = mx + 1 ;            }        }    }    for(i = 1 , mx = 0 ; i <= la ; i ++){        mx = mx > dp[i] ? mx : dp[i] ;    }    return mx ;}int main(){    int la , lb ;    int Tcas ;    scanf("%d" , &Tcas) ;    while(Tcas--){        scanf("%d" , &la) ;        for(int i = 1 ; i <= la ; i ++){            scanf("%d" , &a[i]) ;        }        scanf("%d" , &lb) ;        for(int i = 1 ; i <= lb ; i ++){            scanf("%d" , &b[i]) ;        }        printf("%d\n" , GCIS(la , lb)) ;        if(Tcas)            puts("") ;    }    return 0 ;}