POJ 2127 Greatest Common Increasing Subsequence (动态规划)


http://poj.org/problem?id=2127

       这道题目就是求两个序列的最长公共上升子序列,序列的长度不超过500,那么我们使用O(N^3)复杂度的算法也能过。

       我们假设数组A和B分别为这两个序列,我们定义状态dp[i][j]表示以A[i]和B[j]结尾的并且LCIS的最后一个元素小于A[i]的值,也就是说dp[i][j]并不一定是串A[1--i]和串B[1--j]的LCIS,因为多了一个限制就是该LCIS的最后一个元素必须小于A[i]。那么闲杂我们看看如何来进行状态转移呢?

       如果A[i] == B[j],那么dp[i][j] = max(dp[i`][j-1]) +1;(1<i`<i)

       否则dp[i][j]  = dp[i][j-1]

       路径的话我们只需要在转移的时候进行记录就行了,输出的时候注意判断结束的条件。

       但是这道题很诡异的就是交上去,同一个代码,时而AC时而WA,很不理解。下面贴上代码,希望知道为什么会出现这种诡异现象的大牛能够给予指导,谢谢。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 505;
int dp[MAX][MAX];
int a[MAX],b[MAX];
typedef struct NODE
{
    int x, y;
}Node;
Node path[MAX][MAX];

void print(int n, int m)
{
    //printf("%d %d %d %d\n", n, m, a[n], a[m]);
    if(n == -1 || m == -1)
        return ;
    int x = path[n][m].x;
    int y = path[n][m].y;
    if(dp[x][y] > 0)
        print(x, y);
    if(a[n] == b[m])
        printf("%d ", a[n]);

}

int main()
{
    int n,m;
    while(scanf("%d", &n) != EOF)
    {
        for(int i=1; i<=n; i++)
            scanf("%d", &a[i]);
        scanf("%d", &m);
        for(int i=1; i<=m; i++)
            scanf("%d", &b[i]);
        memset(dp, 0, sizeof(dp));
        int ansans = 0;
        int ansx, ansy;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                int ans = 0;
                int x = -1, y = -1;
                if(a[i] == b[j])
                {
                    for(int k=i-1; k>=1; k--)
                    {
                        if(a[k]<a[i]&&dp[k][j-1]>ans)
                        {
                            ans = dp[k][j-1];
                            x = k;
                            y = j-1;
                        }
                    }
                    ans ++;
                }
                else
                {
                    ans = dp[i][j-1];
                    x = i;
                    y = j-1;
                }
                dp[i][j] = ans;
                path[i][j].x = x;
                path[i][j].y = y;
                if(ansans < ans)
                {
                    ansans = ans;
                    ansx = i;
                    ansy = j;
                }
            }
        }
        printf("%d\n", ansans);
        if(ansans == 0)
        {
            printf("\n");
            continue;
        }
        print(ansx, ansy);
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(POJ 2127 Greatest Common Increasing Subsequence (动态规划))