HDU 1423 - Greatest Common Increasing Subsequence

本文提供了一种求解最长公共上升子序列问题的有效算法,采用动态规划方法,并通过两个不同版本的C++代码实现,详细展示了如何找到两个序列间的最长公共上升子序列。

最长公共上升子序列,仔细分析下会有O(N2)的算法。

#include <cstdio>

int a[500], b[500], A, B;
int _dp[501][501];
#define dp(x,y)    _dp[(x)+1][(y)+1]

#define max(a,b) ((a)>(b)?(a):(b))

int main(void)
{
//    freopen("hdu1423.txt", "r", stdin);
    int T;
    for(scanf("%d", &T); T; ) {
        int ans = 0;
        scanf("%d", &A); for(int i=0; i<A; ++i) scanf("%d", &a[i]);
        scanf("%d", &B); for(int i=0; i<B; ++i) scanf("%d", &b[i]);
        for(int i=0; i<A; ++i) {
            int m = 0;
            for(int j=0; j<B; ++j) {
                dp(i,j)= max(dp(i,j-1), dp(i-1, j));
                if (b[j] < a[i] && dp(i,j) > dp(i,m))
                    m = j;
                else if (b[j] == a[i] && dp(i,j) < dp(i,m) + 1) {
                    dp(i,j) = dp(i,m) + 1;
                    if (ans < dp(i,j)) ans = dp(i,j);
                }
            }
        }
        printf("%d\n", ans);
        if (--T) putchar('\n');
    }
    return 0;
}

 

107456802014-05-15 18:29:46Accepted14230MS312K771 BG++

 

2014/5/17更新:

其实之前题解的转移有问题,dp[i][j]的定义应该是A数组前i个数中、B数组精确到第j个数结尾的最大公共上升子序列。所以就不能有dp[i][j-1]这个转移,因为numB[j-1] > numB[j](仔细想一想)。

#include <cstdio>

int a[500], b[500], A, B;
int _dp[501][501];
#define dp(x,y)    _dp[(x)+1][(y)+1]

int main(void)
{
//    freopen("hdu1423.txt", "r", stdin);
    int T;
    for(scanf("%d", &T); T; ) {
        scanf("%d", &A); for(int i=0; i<A; ++i) scanf("%d", &a[i]);
        scanf("%d", &B); for(int i=0; i<B; ++i) scanf("%d", &b[i]);
        for(int i=0; i<A; ++i) {
            int k = 0;
            for(int j=0; j<B; ++j) {
                dp(i,j)= dp(i-1,j);
                if (b[j] < a[i] && dp(i-1,j) > k) k = dp(i-1,j);
                else if (b[j] == a[i] && dp(i,j) < k + 1) dp(i,j) = k + 1;
            }
        }
        int ans = 0;
        for(int j=0; j<B; ++j)
            if (ans < dp(A-1,j)) ans = dp(A-1,j);
        printf("%d\n", ans);
        if (--T) putchar('\n');
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/e0e1e/p/hdu_1423.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值