题解 | 取数游戏
取数游戏
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;
}
}
查看21道真题和解析