小U的最大连续移动次数问题|豆包MarsCode AI刷题

70 阅读3分钟

问题描述

小U决定在一个 𝑚×𝑛 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:

  1. 只能上坡或者下坡,不能走到高度相同的点。
  2. 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
  3. 每个位置只能经过一次,不能重复行走。

任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。

例如在以下2x2的地图中:

1 2
4 3

中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3。

问题理解

  1. 地图行走规则

    • 小U只能在高度不同的位置之间移动。
    • 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡。
    • 每个位置只能经过一次。
  2. 目标

    • 找到小U在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。

数据结构选择

  • 二维数组:用于表示地图,存储每个位置的高度。
  • 访问标记数组:用于记录每个位置是否已经被访问过。
  • 方向数组:用于表示上下左右四个方向的移动。

算法步骤

  1. 初始化

    • 创建一个二维数组 visited 用于标记每个位置是否被访问过。
    • 创建一个方向数组 directions 用于表示上下左右四个方向的移动。
  2. 深度优先搜索 (DFS)

    • 从每个未访问的位置开始,进行深度优先搜索。
    • 在DFS过程中,根据当前位置的高度和前一个位置的高度,决定下一步是上坡还是下坡。
    • 记录每次DFS的最大深度(即最大移动次数)。
  3. 返回结果

    • 返回所有DFS结果中的最大值。

下面为我写的代码(java)

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static int solution(int m, int n, int[][] a) {
        int ans = 0;
        int i, j;
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        boolean[][] visited = new boolean[m][n];
        
        for (i = 0; i < m; i++) {
            for (j = 0; j < n; j++) {
                ans = Math.max(ans, dfs(a, visited, directions, i, j, true, m, n));
                ans = Math.max(ans, dfs(a, visited, directions, i, j, false, m, n));
            }
        }
        return ans;
    }
    private static int dfs(int[][] a, boolean[][] visited, int[][] directions, int x, int y, boolean isUp, int m, int n) {
        int ans1 = 0;
        visited[x][y] = true;
        for (int[] s : directions) {
            int newx = x + s[0];
            int newy = y + s[1];
            if (newx >= 0 && newx < m && newy >= 0 && newy < n && !visited[newx][newy]) {
                if (isUp && a[newx][newy] < a[x][y]) {
                    ans1 = Math.max(ans1, 1 + dfs(a, visited, directions, newx, newy, false, m, n));
                } else if (!isUp && a[newx][newy] > a[x][y]) {
                    ans1 = Math.max(ans1, 1 + dfs(a, visited, directions, newx, newy, true, m, n));
                }
            }
        }
        visited[x][y] = false;
        return ans1;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int m = scanner.nextInt(), n = scanner.nextInt();
        int i, j;
        int[][] a = new int[m][n];
        for (i = 0; i < m; i++) {
            for (j = 0; j < n; j++)
                a[i][j] = scanner.nextInt();
        }
        System.out.println(solution(m, n, a));
    }
}

关键步骤

  1. visited:用来标记一下该点是否被搜索过
  2. isUp:用于判断对于该点之前的操作是上坡还是下坡

写在最后

这道题思路严谨,解题时需要严格规划好如何判断点位是否符合要求,以及想好dfs函数如何去实现搜索每一个点,需要考虑的地方很多,大家在完成此题的时候可以对dfs算法以及更高级的回溯算法有所了解。