zoukankan      html  css  js  c++  java
  • ACM学习历程—POJ1088 滑雪(dp && 记忆化搜索)

    Description

    Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子        
     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
    一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。      

    Input

    输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。      

    Output

    输出最长区域的长度。      

    Sample Input

    5 5
    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
    

    Sample Output

    25

    这是一道dp题,状态转移方程是:dis[x][y] = max{dis[x-1][y], dis[x][y-1], dis[x+1][y], dis[x][y+1]}。(当满足高度下降时)。

    然后此处采用记忆化搜索。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <vector>
    
    using namespace std;
    
    int xx[] = {-1,  1,  0,  0};
    int yy[] = { 0,  0, -1,  1};
    int Map[105][105], dis[105][105];
    int r, c;
    
    void Input()
    {
        memset(Map, -1, sizeof(Map));
        for (int i = 1; i <= r; ++i)
            for (int j = 1; j <= c; ++j)
                scanf("%d", &Map[i][j]);
        memset(dis, -1, sizeof(dis));
    }
    
    void Dfs(int x, int y)
    {
        for (int i = 0; i < 4; ++i)
        {
            if (Map[x+xx[i]][y+yy[i]] == -1 ||
                Map[x][y] <= Map[x+xx[i]][y+yy[i]])
                continue;
            if (dis[x+xx[i]][y+yy[i]] == -1)
                Dfs(x+xx[i], y+yy[i]);
            dis[x][y] = max(
                            dis[x][y],
                            dis[x+xx[i]][y+yy[i]]+1);
        }
        if (dis[x][y] == -1)
            dis[x][y] = 1;
    }
    
    void Work()
    {
        int ans = -1;
        for (int i = 1; i <= r; ++i)
        {
            for (int j = 1; j <= c; ++j)
            {
                if (dis[i][j] == -1)
                {
                    Dfs(i, j);
                }
                if (ans == -1 || ans < dis[i][j])
                    ans = dis[i][j];
            }
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%d%d", &r, &c) != EOF)
        {
            Input();
            Work();
        }
        return 0;
    }
    
  • 相关阅读:
    2021,6,10 xjzx 模拟考试
    平衡树(二)——Treap
    AtCoder Beginner Contest 204 A-E简要题解
    POJ 2311 Cutting Game 题解
    Codeforces 990G GCD Counting 题解
    NOI2021 SDPTT D2T1 我已经完全理解了 DFS 序线段树 题解
    第三届山东省青少年创意编程与智能设计大赛总结
    Luogu P6042 「ACOI2020」学园祭 题解
    联合省选2021 游记
    Codeforces 1498E Two Houses 题解 —— 如何用结论吊打标算
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4497961.html
Copyright © 2011-2022 走看看