首页 > 代码库 > poj - 1088 - 滑雪(dp)

poj - 1088 - 滑雪(dp)

题意:一个R * C的矩阵(1 <= R,C <= 100),元素代表该点的高度h(0<=h<=10000),从随意点出发,每次仅仅能走上、下、左、右。且将要到的高度要比原高度小,求最长路。

题目链接:http://poj.org/problem?id=1088

——>>设dp[i][j]表示从ij位置出发的最长路,则状态转移方程为:

dp[x][y] = max(dp[x][y], Dp(nNewX, nNewY) + 1);

时间复杂度:O(R * C)

#include <cstdio>
#include <cstring>
#include <algorithm>

using std::max;

const int MAXN = 100 + 10;

int R, C;
int nHeight[MAXN][MAXN];
int dp[MAXN][MAXN];
int dx[] = {-1, 1,  0, 0};
int dy[] = { 0, 0, -1, 1};

void Read()
{
    for (int i = 1; i <= R; ++i)
    {
        for (int j = 1; j <= C; ++j)
        {
            scanf("%d", &nHeight[i][j]);
        }
    }
}

int Dp(int x, int y)
{
    if (dp[x][y] != -1)
    {
        return dp[x][y];
    }

    int& nRet = dp[x][y];
    nRet = 1;
    for (int i = 0; i < 4; ++i)
    {
        int nNewX = x + dx[i];
        int nNewY = y + dy[i];
        if (nNewX >= 1
            && nNewX <= R
            && nNewY >= 1
            && nNewY <= C
            && nHeight[nNewX][nNewY] < nHeight[x][y])
        {
            nRet = max(nRet, Dp(nNewX, nNewY) + 1);
        }
    }

    return nRet;
}

void Solve()
{
    int nRet = 0;

    memset(dp, -1, sizeof(dp));
    for (int i = 1; i <= R; ++i)
    {
        for (int j = 1; j <= C; ++j)
        {
            if (dp[i][j] == -1)
            {
                Dp(i, j);
            }
        }
    }

    for (int i = 1; i <= R; ++i)
    {
        for (int j = 1; j <= C; ++j)
        {
            if (dp[i][j] > nRet)
            {
                nRet = dp[i][j];
            }
        }
    }

    printf("%d\n", nRet);
}

int main()
{
    while (scanf("%d%d", &R, &C) == 2)
    {
        Read();
        Solve();
    }
    return 0;
}


poj - 1088 - 滑雪(dp)