• AcWing 901. 滑雪


    地址 https://www.acwing.com/problem/content/description/903/

    题目描述
    给定一个R行C列的矩阵,表示一个矩形网格滑雪场。

    矩阵中第 i 行第 j 列的点表示滑雪场的第 i 行第 j 列区域的高度。

    一个人从滑雪场中的某个区域内出发,每次可以向上下左右任意一个方向滑动一个单位距离。

    当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。

    下面给出一个矩阵作为例子:

    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-2-1。

    在给定矩阵中,最长的滑行轨迹为25-24-23-…-3-2-1,沿途共经过25个区域。

    现在给定你一个二维矩阵表示滑雪场各区域的高度,请你找出在该滑雪场中能够完成的最长滑雪轨迹,并输出其长度(可经过最大区域数)。

    输入格式
    第一行包含两个整数R和C。

    接下来R行,每行包含C个整数,表示完整的二维矩阵。

    输出格式
    输出一个整数,表示可完成的最长滑雪长度。

    数据范围
    1≤R,C≤300,
    0≤矩阵中整数≤10000

    输入样例:
    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
    输出样例:
    25

    算法1
    一开始 写的常规DFS
    但是在某些数据 超时。果然没那么简单

    代码

     1 #include <iostream>
     2 #include <vector>
     3 
     4 using namespace std;
     5 
     6 const int N = 310;
     7 int n,m;
     8 int maxlen = -1;
     9 vector<vector<int>>  vv;
    10 
    11 int addx[] = {1,-1,0,0};
    12 int addy[] = {0,0,1,-1};
    13 
    14 void dfs(int x,int y,int len)
    15 {
    16     if(len > maxlen) maxlen = len;
    17 
    18     for(int i = 0;i < 4;i++){
    19         int newx = x + addx[i];
    20         int newy = y + addy[i];
    21 
    22         if(newx >=0 && newx < n && newy >=0 && newy < m &&
    23             vv[newx][newy] < vv[x][y])
    24         {
    25             dfs(newx,newy,len+1);        
    26         }
    27     }
    28 }
    29 
    30 
    31 int main()
    32 {
    33     cin >> n >> m;
    34 
    35     for(int i = 0; i < n;i++){
    36         vector<int> v;
    37         vv.push_back(v);
    38         for(int j = 0;j< m;j++){
    39             int t =0;
    40             cin >> t;
    41             vv[i].push_back(t);    
    42         }
    43     }
    44 
    45 
    46     for(int i = 0; i < n;i++){
    47         for(int j = 0;j < m;j++){
    48             int len =0;
    49             dfs(i,j,len);
    50         }
    51     }
    52 
    53     cout << maxlen+1  << endl;
    54 
    55     return 0;
    56 }
    View Code

    算法2
    使用记忆化数组 记录每个点的最大滑动长度
    遍历每个点作为起点
    然后检测该点四周的点 如果可以滑动到其他的点
    那么该点的最大滑动长度 就是其他可以滑到的点的滑动长度+1
    dp[i][j] = max(dp[i][j-1], dp[i][j+1],dp[i-1][j],dp[i+1][j])

    由于滑雪是必须滑到比当前低的点  在任意一个起点的dfs中,不会存在一个点多次进入的问题
    如果该点的dp[][] 不为初始化值 那么就说明计算过 不必再次计算。

    按照上述公式 代码如下 AC

    #include <iostream>
    
    using namespace std;
    
    const int N = 310;
    int R,C;
    
    int arr[N][N];
    int dp[N][N];
    
    int maxlen = -1;
    
    int addx[] = {1,-1,0,0};
    int addy[] = {0,0,1,-1};
    
    int  Dfs(int x,int y)
    {
        if(dp[x][y] != 0) return dp[x][y];
    
    
         for(int i = 0;i < 4;i++){
            int newx = x + addx[i];
            int newy = y + addy[i];
    
            if(newx >=0 && newx < C && newy >=0 && newy < R &&
                arr[newx][newy] < arr[x][y])
            {
                dp[x][y] = max(dp[x][y], Dfs(newx,newy) +1);
            }
        }
        return dp[x][y];
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
    
      cin >> R >>C;
    
      for(int i = 0; i < R;i++){
          for(int j=0;j<C;j++){
            cin >> arr[i][j];    
          }
      }
    
      for(int i = 0; i < R;i++){
          for(int j = 0;j< C;j++){
            int len = Dfs(i,j);   
            maxlen = max(maxlen,len);
          }
      }  
    
      cout << maxlen +1  << endl;
    
        return 0;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    map按照值排序
    结构体的三种排序方式
    归并排序
    数组模拟双向链表
    二刷斐波那契高精度
    2019年9月训练(贰)区间DP (luogu 4290)
    2019年9月训练(壹)数位DP (HDU 2089)
    2019年8月训练(贰)
    2019年8月训练(壹)二分,三分
    2019年7月训练(柒)
  • 原文地址:https://www.cnblogs.com/itdef/p/11668749.html
Copyright © 2020-2023  润新知