首页 > 试题广场 >

滑雪

[编程题]滑雪
  • 热度指数:4008 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个 的矩阵,矩阵中的数字表示滑雪场各个区域的高度,你可以选择从任意一个区域出发,并滑向任意一个周边的高度严格更低的区域(周边的定义是上下左右相邻的区域)。请问整个滑雪场中最长的滑道有多长?(滑道的定义是从一个点出发的一条高度递减的路线)。
(本题和矩阵最长递增路径类似,该题是当年NOIP的一道经典题)

数据范围: ,矩阵中的数字满足

输入描述:
第一行输入两个正整数 n 和 m 表示矩阵的长宽。
后续 n 行输入中每行有 m 个正整数,表示矩阵的各个元素大小。



输出描述:
输出最长递减路线。

示例1

输入

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

说明

从25出发,每次滑向周边比当前小 1 的区域。 25->24->23->22->......->1  
import java.util.Scanner;

// 回溯
public class Main {
    private static int res = 1; // 结果:初始1段
    private static boolean[][] visited; // 标记访问
    private static int[][] direction = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 方向

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(), m = in.nextInt();
        visited = new boolean[n][m];
        int[][] grid = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                grid[i][j] = in.nextInt();
            }
        }

        for (int i = 0; i < n; i++) { // [i,j]每个点都尝试起始点
            for (int j = 0; j < m; j++) {
                visited[i][j] = true;
                backtrack(grid, i, j, 1);
                visited[i][j] = false;
            }
        }
        System.out.println(res);
    }

    // 回溯
    private static void backtrack(int[][] grid, int x, int y, int cnt) {
        int n = grid.length, m = grid[0].length;
        for (int k = 0; k < 4; k++) {
            int i = x + direction[k][0], j = y + direction[k][1];
            if (i < 0 || i >= n || j < 0 || j >= m ||
                    visited[i][j] || grid[i][j] >= grid[x][y])
                continue;
            visited[i][j] = true;
            res = Math.max(res, cnt + 1);
            backtrack(grid, i, j, cnt + 1); // 下一层
            visited[i][j] = false;
        }
    }
}

发表于 2025-03-25 16:23:34 回复(0)