P1434 [SHOI2002]滑雪 记忆化搜索,深度搜索,动态规划

第一篇题解,实际上是几天前做的题目

P1434 [SHOI2002]滑雪 

1   2   3   4   5
16  17  18  19  6
15  24  25  20  7
14  23  22  21  8
13  12  11  10  9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-\ldots…-33-22-11 更长。事实上,这是最长的一条。

输出区域中最长滑坡的长度。

深度搜索dsf(int x, int y)返回从(x,y)滑下的最长路径,对每个点调用该函数后取最大值即为答案.

搜索路径较多,使用数组 dp[x][y]记录调用dfs(x, y)的返回值以加速.(实际上这题也有dp的状态转移的思想)

对于每次(每个点)的搜索,检查其上下左右四个相邻位置(nx,ny)对于所有高度小于当前位置的相邻位置,取dfs(nx,ny)返回值最大者,则当前位置的返回值为该最大值与其原本值(若有)的最大者+1.若所有相邻位置高度均大于当前位置(bad),则该点的返回值为1.

细节:1.对于存储高度的数组,从(0,0)开始直到(r+1,c+1)均初始化为INF,而读入数据存储到从(1,1)开始直到(r,c)的位置,使得INF形成包围之势防止滑雪滑出场地.

#  #  #   #   #   #  #
# 1   2   3   4   5  #
# 16  17  18  19  6  #
# 15  24  25  20  7  #
# 14  23  22  21  8  #
# 13  12  11  10  9  #
#  #  #   #   #   #  #    (#指INF)

2.数组dp初始化为-1.


 

可以证明,第一次调用dfs会在某个高度低于所有相邻位置的点处返回1并在此处终止一次递归,所有的递归总会达到正确的终止条件,虽然直觉让人觉得不停地对陌生的点调用dfs会陷入麻烦.

 

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 100000000

int s[110][110], dp[110][110];
int r, c, dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};

int dfs(int x, int y)
{
    bool bad = true;
    if(dp[x][y] > 0)
        return dp[x][y];
    else
        for(int i = 0; i < 4; i++)
        {
            int nx = x + dx[i], ny = y + dy[i];
            if(s[nx][ny] < s[x][y])
            {
                dp[x][y] = max(dfs(nx, ny), dp[x][y]);
                bad = false;
            }
        }
    if(bad)
        return dp[x][y] = 1;        //end
    else
        return ++dp[x][y];
}

int main()
{
    cin >> r >> c;
    for(int i = 0; i <= r + 1; i++)
        for(int j = 0; j <= c + 1; j++)
            s[i][j] = INF;
    for(int i = 1; i <= r; i++)
        for(int j = 1; j <= c; j++)
            cin >> s[i][j];

    memset(dp, -1, sizeof(dp));
    for(int i = 1; i <= r; i++)
        for(int j = 1; j <= c; j++)
            dfs(i, j);

    int ans = -1;
    for(int i = 1; i <= r; i++)
        for(int j = 1; j <= c; j++)
            ans = max(ans, dp[i][j]);
    printf("%d\n", ans);

    return 0;
}

 

posted @ 2020-11-18 16:59  goverclock  阅读(145)  评论(1编辑  收藏  举报