小华地图寻宝

题目描述

小华按照地图去寻宝,地图上被划分成 m 行和 n 列的方格,横纵坐标范围分别是 0, n-10, m-1

在横坐标和纵坐标的数位之和不大于 k 的方格中存在黄金(每个方格中仅存在一克黄金),但横坐标和纵坐标数位之和大于 k 的方格存在危险不可进入。小华从入口 (0,0) 进入,任何时候只能向左,右,上,下四个方向移动一格。

请问小华最多能获得多少克黄金?

输入描述

坐标取值范围如下:

0 ≤ m ≤ 50

0 ≤ n ≤ 50

k 的取值范围如下:

0 ≤ k ≤ 100

输入中包含3个字数,分别是m, n, k

输出描述

输出小华最多能获得多少克黄金

用例

输入 40 40 18
输出 1484
输入 5 4 7
输出 20

解题思路

题目规则再梳理

  1. 地图是 m行 n列 的方格:
  • 横坐标(列)范围:0 ~ n-1
  • 纵坐标(行)范围:0 ~ m-1
  1. 黄金判定规则:对坐标 (x, y),x 的每一位数字之和 + y 的每一位数字之和 ≤ k,这个格子就有 1 克黄金,能走;反之格子危险,绝对不能进入。

    举个例子:坐标(14, 23)

    x=14 数位和:1+4=5,y=23 数位和:2+3=5,总和10。如果 k≥10,这个格子可走、有黄金。

  2. 移动规则:从起点 (0, 0) 出发,上下左右 4 个方向每次只能走 1 格,不能斜着走。

  3. 最终目标:统计从起点出发,所有能走到的、符合黄金条件的格子总数(每个格子 1 克黄金)。

  4. 核心解题逻辑

步骤 1:先写「数位和计算工具方法」

我们需要一个函数,输入一个数字,能算出它所有位上的数字相加的和。比如输入25,返回2+5=7;输入9,返回9;输入0,返回0。

步骤 2:用 BFS 广度优先搜索遍历所有可达格子

BFS 就是一层一层往外扩散遍历,非常适合这种网格四方向走路、找所有可达点的场景,逻辑就像水从起点慢慢往四周蔓延:

起点固定是 (0, 0),首先判断起点本身是否符合条件(0的数位和+0的数位和=0,只要 k≥0 就一定合法)。

准备一个队列,用来存放接下来要去访问的格子坐标;再准备一个访问标记数组,记录哪些格子已经走过了,避免重复走、重复统计黄金(防止原地来回绕圈死循环)。

循环遍历队列:每次拿出队首的格子,黄金计数 + 1;然后往上下左右 4 个方向分别探索相邻格子。

对每一个相邻格子,做 3 个合法性校验,全部满足才入队:

① 坐标没有越界(在地图范围内:行0<=y<m,列0<=x<n)

② 这个格子还没有被访问过

③ 该坐标的横纵坐标数位之和 ≤ k(有黄金、不危险)

直到队列为空,所有能走到的格子全部遍历完毕,最终的计数就是答案。

为什么选 BFS 而不是 DFS?

BFS(广度优先):层序遍历,从起点一圈圈扩散,逻辑直观,天然适合网格可达性统计,不容易出现深度递归栈溢出。

DFS(深度优先):一条路走到黑再回溯,虽然也能做,但网格最大 50*50,递归深度过高有栈风险,且代码可读性不如 BFS。

java实现

java 复制代码
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * 小华寻宝问题(网格BFS广度优先搜索)
 * 题目:从(0,0)出发,四方向移动,横纵坐标数位和<=k的格子有黄金,统计所有可达格子总数
 */
public class TreasureHunt {
    // 上下左右 4个移动方向的坐标偏移量
    private static final int[][] DIRS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static void main(String[] args) {
        // 1. 控制台输入:依次输入 m(行数), n(列数), k(数位和上限)
        Scanner scanner = new Scanner(System.in);
        int m = scanner.nextInt();
        int n = scanner.nextInt();
        int k = scanner.nextInt();
        scanner.close();

        // 2. 调用核心方法计算结果,并输出
        int maxGold = getMaxGold(m, n, k);
        System.out.println(maxGold);
    }

    /**
     * 核心方法:计算最多能获得的黄金数量
     * @param m 地图总行数,纵坐标范围 [0, m-1]
     * @param n 地图总列数,横坐标范围 [0, n-1]
     * @param k 横纵坐标数位和上限
     * @return 可达的黄金格子总数
     */
    public static int getMaxGold(int m, int n, int k) {
        // 边界情况:地图为空,直接返回0
        if (m == 0 || n == 0) {
            return 0;
        }

        // 访问标记数组:visited[y][x] = true 代表坐标(x,y)已经走过,避免重复遍历
        boolean[][] visited = new boolean[m][n];
        // BFS队列,存储待遍历的坐标 (横坐标x, 纵坐标y)
        Queue<int[]> queue = new LinkedList<>();

        // 初始化:起点(0,0),先判断起点是否合法
        if (countBitSum(0) + countBitSum(0) <= k) {
            queue.offer(new int[]{0, 0});
            visited[0][0] = true;
        }

        int goldCount = 0; // 黄金总数统计

        // BFS主循环:队列不为空就一直遍历
        while (!queue.isEmpty()) {
            // 取出队首当前格子坐标
            int[] curr = queue.poll();
            int x = curr[0]; // 横坐标(列)
            int y = curr[1]; // 纵坐标(行)

            // 当前格子合法有黄金,计数+1
            goldCount++;

            // 遍历上下左右4个方向,探索相邻格子
            for (int[] dir : DIRS) {
                int newX = x + dir[0];
                int newY = y + dir[1];

                // 四重合法性校验,全部满足才可以入队访问
                // 1. 横坐标不越界:0 <= newX < n
                // 2. 纵坐标不越界:0 <= newY < m
                // 3. 该格子从未访问过
                // 4. 横纵坐标数位之和 不超过k(安全、有黄金)
                if (newX >= 0 && newX < n
                        && newY >= 0 && newY < m
                        && !visited[newY][newX]
                        && (countBitSum(newX) + countBitSum(newY) <= k)) {
                    // 标记已访问,加入队列待遍历
                    visited[newY][newX] = true;
                    queue.offer(new int[]{newX, newY});
                }
            }
        }

        return goldCount;
    }

    /**
     * 工具方法:计算一个数字所有位上的数字之和
     * 例如:num=25 → 2+5=7;num=0 → 0;num=103 →1+0+3=4
     * @param num 输入数字
     * @return 数位之和
     */
    private static int countBitSum(int num) {
        int sum = 0;
        while (num > 0) {
            sum += num % 10; // 取个位数字累加
            num = num / 10;  // 去掉个位数字
        }
        return sum;
    }
}
相关推荐
To_OC5 小时前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安10 小时前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者13 小时前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent
kisshyshy19 小时前
从递归到迭代,一文吃透二叉树的核心知识与 JavaScript 实现
javascript·算法·代码规范
To_OC1 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
用户938515635071 天前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC1 天前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥2 天前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程