zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    
        return 0;
    }
  • 相关阅读:
    jchdl
    jchdl
    UVa 10256 (判断两个凸包相离) The Great Divide
    UVa 11168 (凸包+点到直线距离) Airport
    LA 2572 (求可见圆盘的数量) Kanazawa
    UVa 10652 (简单凸包) Board Wrapping
    UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
    UVa 10674 (求两圆公切线) Tangents
    UVa 11796 Dog Distance
    LA 3263 (平面图的欧拉定理) That Nice Euler Circuit
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14000896.html
Copyright © 2011-2022 走看看