2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(省赛)RC-u3题解

题目:暖炉与水豚

源题目地址:https://pintia.cn/problem-sets/1813039306479005696/exam/problems/type/7?problemSetProblemId=1813039385617129474

问题描述

给定一个N×M的矩阵,包含水豚(‘c’表示冷,‘w’表示暖)、暖炉(‘m’)和空格(’.’)。暖炉可以温暖其3×3范围内的水豚。题目保证最多只有一只水豚的状态异常(周围没有暖炉却显示为暖)。需要找出哪些空格可能藏有暖炉,使得所有水豚状态合法。

解题思路

  1. 输入解析:
    • 矩阵大小为 N×M N \times M N×M(1≤N,M≤1000 1 \leq N, M \leq 1000 1≤N,M≤1000)。
    • 矩阵元素为:
      • .:空格(可能隐藏暖炉)。
      • c:冷的要命的水豚。
      • w:暖呼呼的水豚。
      • m:已知的暖炉。
    • 最多有一个水豚状态异常(周围没有暖炉却为 w)。
  2. 合法矩阵的定义:
    • 每个 w(暖呼呼的水豚)必须在其 3×3 范围内(以水豚为中心,包含自身及周围 8 个格子)至少有一个暖炉(m 或隐藏的暖炉)。
    • 每个 c(冷的水豚)在其 3×3 范围内不能有任何暖炉。
    • 目标是找出所有空格(.),在这些格子放置一个暖炉后,矩阵状态合法。
  3. 异常水豚的处理:
    • 异常水豚是指一个 w,其 3×3 范围内没有已知的暖炉(m)。
    • 最多只有一个这样的水豚。
    • 如果存在这样的水豚,隐藏的暖炉必须位于其 3×3 范围内,以使其状态合法。
  4. 解题步骤:
    • 读取矩阵并记录所有水豚(c 和 w)和已知暖炉(m)的位置。
    • 检查是否存在异常水豚(w 且 3×3 范围内无暖炉)。
    • 如果有异常水豚,检查其 3×3 范围内的所有空格(.),验证每个空格是否可能为隐藏暖炉。
    • 如果没有异常水豚,检查所有空格,验证是否可以在其中放置暖炉使矩阵合法。
    • 对于每个空格,模拟放置暖炉,检查所有水豚的状态是否合法:
      • 每个 w 的 3×3 范围内必须有至少一个暖炉(包括已知和假设的暖炉)。
      • 每个 c 的 3×3 范围内不能有任何暖炉。
    • 输出所有满足条件的空格,按行优先(r 从小到大,c 从小到大)排序。
  5. 边界情况:
    • 如果没有空格能使矩阵合法,输出 Too cold!。
    • 需要处理矩阵边界,确保 3×3 范围不越界。

代码实现

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

public class Main {
    static int N, M;
    static char[][] grid;
    static List<int[]> capybaras; // 存储所有水豚的位置和状态 [r, c, state]
    static List<int[]> heaters; // 存储所有已知暖炉的位置 [r, c]
    static List<int[]> emptyCells; // 存储所有空格的位置 [r, c]

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取矩阵大小
        N = scanner.nextInt();
        M = scanner.nextInt();
        grid = new char[N][M];
        capybaras = new ArrayList<>();
        heaters = new ArrayList<>();
        emptyCells = new ArrayList<>();

        // 读取矩阵并记录水豚、暖炉和空格的位置
        for (int i = 0; i < N; i++) {
            String line = scanner.next();
            for (int j = 0; j < M; j++) {
                grid[i][j] = line.charAt(j);
                if (grid[i][j] == 'c' || grid[i][j] == 'w') {
                    capybaras.add(new int[] { i, j, grid[i][j] });
                } else if (grid[i][j] == 'm') {
                    heaters.add(new int[] { i, j });
                } else if (grid[i][j] == '.') {
                    emptyCells.add(new int[] { i, j });
                }
            }
        }

        // 找到异常水豚(如果存在)
        int[] anomaly = findAnomaly();
        List<int[]> possibleHeaters = new ArrayList<>();

        if (anomaly != null) {
            // 如果有异常水豚,检查其 3x3 范围内的空格
            int r = anomaly[0], c = anomaly[1];
            for (int i = Math.max(0, r - 1); i <= Math.min(N - 1, r + 1); i++) {
                for (int j = Math.max(0, c - 1); j <= Math.min(M - 1, c + 1); j++) {
                    if (grid[i][j] == '.') {
                        if (isValidHeater(i, j)) {
                            possibleHeaters.add(new int[] { i, j });
                        }
                    }
                }
            }
        } else {
            // 如果没有异常水豚,检查所有空格
            for (int[] cell : emptyCells) {
                if (isValidHeater(cell[0], cell[1])) {
                    possibleHeaters.add(cell);
                }
            }
        }

        // 输出结果
        if (possibleHeaters.isEmpty()) {
            System.out.println("Too cold!");
        } else {
            // 按 r 升序,r 相同时按 c 升序排序
            possibleHeaters.sort((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
            for (int[] pos : possibleHeaters) {
                System.out.println((pos[0] + 1) + " " + (pos[1] + 1));
            }
        }
    }

    // 寻找异常水豚(暖呼呼但周围无暖炉)
    static int[] findAnomaly() {
        for (int[] capybara : capybaras) {
            if (capybara[2] == 'w') {
                boolean hasHeater = false;
                int r = capybara[0], c = capybara[1];
                for (int i = Math.max(0, r - 1); i <= Math.min(N - 1, r + 1); i++) {
                    for (int j = Math.max(0, c - 1); j <= Math.min(M - 1, c + 1); j++) {
                        if (grid[i][j] == 'm') {
                            hasHeater = true;
                            break;
                        }
                    }
                    if (hasHeater)
                        break;
                }
                if (!hasHeater) {
                    return capybara;
                }
            }
        }
        return null;
    }

    // 检查在 (r, c) 放置暖炉后矩阵是否合法
    static boolean isValidHeater(int r, int c) {
        // 模拟在 (r, c) 放置暖炉
        List<int[]> tempHeaters = new ArrayList<>(heaters);
        tempHeaters.add(new int[] { r, c });

        // 检查所有水豚的状态
        for (int[] capybara : capybaras) {
            int cr = capybara[0], cc = capybara[1];
            boolean hasHeater = false;
            for (int[] heater : tempHeaters) {
                int hr = heater[0], hc = heater[1];
                if (Math.abs(cr - hr) <= 1 && Math.abs(cc - hc) <= 1) {
                    hasHeater = true;
                    break;
                }
            }
            // 暖呼呼的水豚必须有暖炉
            if (capybara[2] == 'w' && !hasHeater) {
                return false;
            }
            // 冷的水豚不能有暖炉
            if (capybara[2] == 'c' && hasHeater) {
                return false;
            }
        }
        return true;
    }
}

关键点说明

  1. 输入处理:读取矩阵并分类存储水豚、暖炉和空格的位置。

  2. 异常检测findAnomaly()方法检查所有暖呼呼的水豚是否都有暖炉在附近。

  3. 潜在暖炉搜索:有异常水豚时,只搜索其3×3范围内的空格,无异常水豚时,搜索所有空格。

  4. 暖炉验证isValidHeater()方法模拟放置暖炉后验证所有水豚状态是否合法。

  5. 结果输出:按要求排序并输出可能的暖炉位置,或"Too cold!"。

复杂度分析

  • 时间复杂度:O(NM + K(N*M)),其中K是潜在暖炉位置数量。
  • 空间复杂度:O(N*M),用于存储矩阵和各类位置列表。

你可能感兴趣的:(机器人,java,开发语言)