题解 | 取数游戏

取数游戏

https://www.nowcoder.com/practice/b002b8eb564245fdbb8a02db8dcf03e4

import java.io.*;
import java.util.*;

public class Main {
   private static int N, M;  // 网格的行数和列数
    private static int[][] grid;  // 存储网格数据的二维数组
    private static boolean[][] used;  // 标记网格位置是否被使用过的二维数组
    private static long ans;  // 存储最终答案的最大值

    /**
     * 主方法,程序的入口点
     *
     * @param args 命令行参数
     * @throws IOException 可能抛出IO异常
     */
    public static void main(String[] args) throws IOException {
        // 使用BufferedReader从标准输入读取数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 使用PrintWriter向标准输出写入数据
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));


        // 读取测试用例数量
        int T = Integer.parseInt(br.readLine().trim());

        // 处理每个测试用例
        for (int i = 0; i < T; i++) {
            String[] str = br.readLine().split("\\s+");
            N = Integer.parseInt(str[0]);
            M = Integer.parseInt(str[1]);

            grid = new int[N][M];  // 初始化网格数组
            used = new boolean[N][M];  // 初始化使用标记数组
            ans = 0;  // 重置答案为0

            // 读取网格数据
            for (int j = 0; j < N; j++) {
                String[] gridStr = br.readLine().trim().split("\\s+");
                for (int k = 0; k < M; k++) {
                    grid[j][k] = Integer.parseInt(gridStr[k]);  // 将字符串转换为整数存入网格
                }
            }
            backtrack(0, 0);  // 从第一个位置开始回溯
            out.println(Math.max(ans, 0));  // 输出最大答案,至少为0
        }

        out.flush();  // 刷新输出缓冲区
        out.close();  // 关闭输出流
        br.close();  // 关闭输入流


    }


    /**
     * 回溯算法方法,用于在网格中寻找最大可能值
     *
     * @param index  当前处理的位置索引,从0到N*M-1
     * @param curAns 当前累计的答案值
     */
    private static void backtrack(int index, long curAns) {
        // 基本情况:如果已经处理完所有网格位置
        if (index == N * M) {
            // 更新最大答案值
            ans = Math.max(ans, curAns);
            return;
        }

        // 计算当前索引对应的行和列
        int row = index / M;  // 计算当前行号
        int col = index % M;  // 计算当前列号

        // 情况1:不选择当前网格位置,直接处理下一个位置
        backtrack(index + 1, curAns);

        // 情况2:如果当前位置可以安全选择
        if (isSafe(row, col)) {
            // 标记当前位置为已使用
            used[row][col] = true;
            // 选择当前位置,累加其值并处理下一个位置
            backtrack(index + 1, curAns + grid[row][col]);
            // 回溯:撤销当前位置的使用标记
            used[row][col] = false;
        }
    }

    /**
     * 检查指定位置是否安全,即其周围8个方向(包括自身)是否都没有被使用过
     *
     * @param row 当前行索引
     * @param col 当前列索引
     * @return 如果周围8个方向都没有被使用过,返回true;否则返回false
     */
    private static boolean isSafe(int row, int col) {
        // 遍历当前位置的周围8个方向(包括自身)
        for (int drow = -1; drow <= 1; drow++) {
            for (int dcol = -1; dcol <= 1; dcol++) {
                // 计算下一个位置的行索引
                int nextRow = row + drow;
                // 计算下一个位置的列索引
                int nextCol = col + dcol;

                // 检查下一个位置是否在有效范围内
                if (nextRow >= 0 && nextRow < N && nextCol >= 0 && nextCol < M) {
                    // 如果下一个位置已经被使用过,则返回false
                    if (used[nextRow][nextCol]) {
                        return false;
                    }
                }

            }
        }
        // 如果周围8个方向都没有被使用过,则返回true
        return true;
    }
}

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务