洛谷P1434 [SHOI2002] 滑雪(dp的思想和dfs结合)

本文介绍了一个使用伪代码和C语言实现的算法,通过深度优先搜索(DFS)寻找给定矩阵中从每个点出发的最大滑坡长度,利用动态规划优化避免重复计算,最后输出全局最优的滑坡长度。
摘要由CSDN通过智能技术生成

伪代码

function findLongestSlope(R, C, heights):
    max_slope_length = 0
    
    for i from 1 to R:
        for j from 1 to C:
            slope_length = DFS(i, j, heights)
            max_slope_length = max(max_slope_length, slope_length)
    
    return max_slope_length

function DFS(x, y, heights):
    // 当前点作为起点进行深度优先搜索
    // 初始滑坡长度为1
    current_slope_length = 1
    
    for each direction (dx, dy) from (x, y):
        new_x = x + dx
        new_y = y + dy
        
        // 如果新点在区域内,并且高度低于当前点,则继续搜索
        if isValid(new_x, new_y) and heights[new_x][new_y] < heights[x][y]:
            slope_length = 1 + DFS(new_x, new_y, heights)
            // 更新最长滑坡长度
            current_slope_length = max(current_slope_length, slope_length)
    
    return current_slope_length

function isValid(x, y):
    // 检查新点是否在区域内
    return 1 <= x <= R and 1 <= y <= C

 

 

#include <stdio.h>

#define MAX_SIZE 100

int R, C;
int matrix[MAX_SIZE][MAX_SIZE];
int dp[MAX_SIZE][MAX_SIZE];



// 定义四个方向的偏移量(四个方向找的固定格式)
int dx[4] = { -1, 1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };

// 从位置 (x, y) 开始找最长滑坡的长度
int dfs(int x, int y) {
    if (dp[x][y] != 0) {
        return dp[x][y];
    }
    dp[x][y] = 1; // 初始值为1

    // 尝试向四个方向滑动
    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        // 判断是否越界以及高度是否递减
        if (nx >= 0 && nx < R && ny >= 0 && ny < C && matrix[nx][ny] < matrix[x][y]) {
            dp[x][y] = (dp[x][y] > dfs(nx, ny) + 1) ? dp[x][y] : dfs(nx, ny) + 1;//更新局部最优
        }
    }
    return dp[x][y];
}

int main() {
    scanf("%d %d", &R, &C);
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }

    int longest_slope = 0;
    // 对每个位置调用 dfs
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            longest_slope = (longest_slope > dfs(i, j)) ? longest_slope : dfs(i, j);//全局最优比较
        }
    }

    printf("%d\n", longest_slope);

    return 0;
}

整体思路如下:

  1. 从每个点出发,以该点为起点进行深度优先搜索(DFS)。
  2. 在搜索过程中,判断当前点是否可以向下滑行,即比其周围相邻点的高度低,如果可以向下滑行,则继续搜索下一个相邻点,并更新滑坡长度(更新局部最优)。
  3. 搜索过程中记录每个点处得到的最长滑坡长度,最终输出最大的滑坡长度即可(全局最优的比较)。

 ps:

1.if (dp[x][y] != 0) { return dp[x][y]; }这个是为了避免重复计算同一个点。

1 2 3
4 5 6
7 8 9

比如dp记录了5的最优路径是长度,则下一个点6向左的话,直接用5记录好的最优长度5即可。

2.dp[x][y] = (dp[x][y] > dfs(nx, ny) + 1) ? dp[x][y] : dfs(nx, ny) + 1;怎么理解

这行代码的作用是更新当前位置 (x, y) 的最优值 dp[x][y]。它的意思可以理解为:

  • 如果当前位置 (x, y) 的最优值已经被计算过,并且已经存储在 dp[x][y] 中,那么我们比较已经存储的最优值 dp[x][y] 和从 (nx, ny) 位置出发进行深度优先搜索得到的最优值 dfs(nx, ny) + 1,然后选择其中较大的值作为当前位置 (x, y) 的最优值。
  • 如果当前位置 (x, y) 的最优值尚未被计算过,即 dp[x][y] 的值为 0,那么我们直接将从 (nx, ny) 位置出发进行深度优先搜索得到的最优值 dfs(nx, ny) + 1 作为当前位置 (x, y) 的最优值。

这样做的目的是确保我们每次更新 dp[x][y] 的值时,都能选择最优的结果。如果当前位置已经有最优值存储在 dp[x][y] 中,我们就不需要重新计算,而是比较已有的最优值和新的可能性中的最优值,选择更大的那个作为当前位置的最优值。

User

3.为什么要 dfs(nx, ny) + 1而不是 dfs(nx, ny)

在这个问题中,我们需要找到从当前位置 (x, y) 出发的最长滑坡长度。当我们从当前位置 (x, y) 转移到相邻位置 (nx, ny) 时,这一步的长度是 1,因为我们每次只能移动到相邻位置。因此,我们需要将当前位置 (x, y) 的最优值更新为从相邻位置 (nx, ny) 出发的最优值 dfs(nx, ny) 加上当前步的长度 1,即 dfs(nx, ny) + 1

换句话说,我们考虑的是从当前位置 (x, y) 出发的最长滑坡,因此需要将当前位置的最优值更新为从相邻位置 (nx, ny) 出发的最长滑坡长度加上当前这一步的长度 1。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值