第一行有一个正整数
(
),表示了有
组数据。
对于每一组数据,第一行有两个正整数
(
),表示了数字矩阵为
行
列。
接下来
行,每行
个非负整数,描述了这个数字矩阵,满足
。
输出共
行,每行一个非负整数,输出所求得的答案。
1 3 3 1 1 1 1 1 1 1 1 1
4
#include <stdio.h>
#include <string.h>
int N, M;
int max_result;
// 解决函数:使用DFS搜索所有可能的选取方案
// matrix: 数字矩阵
// used: 标记哪些位置已经被选取
// x, y: 当前要处理的位置坐标
// sum: 当前已选取数字的总和
void solve(int matrix[N][M], int used[N][M], int x, int y, int sum) {
// 如果已经处理完所有行,更新最大值并返回
if (x >= N) {
if (sum > max_result) max_result = sum;
return;
}
// 计算下一个要处理的位置
int next_x = x;
int next_y = y + 1;
// 如果当前行处理完了,移动到下一行的第一个位置
if (next_y >= M) {
next_x = x + 1;
next_y = 0;
}
// 选择1:不选当前位置的数字
// 直接跳到下一个位置,总和不变
solve(matrix, used, next_x, next_y, sum);
// 选择2:尝试选取当前位置的数字
// 首先检查是否能选取(周围8个方向没有已选的数字)
int can_choose = 1; // 假设可以选取
// 检查周围8个方向(包括对角线)
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
// 跳过当前位置自身
if (dx == 0 && dy == 0) continue;
// 计算相邻位置的坐标
int neighbor_x = x + dx;
int neighbor_y = y + dy;
// 检查相邻位置是否在矩阵范围内且已经被选取
if (neighbor_x >= 0 && neighbor_x < N &&
neighbor_y >= 0 && neighbor_y < M &&
used[neighbor_x][neighbor_y]) {
can_choose = 0; // 发现相邻位置已选,不能选当前位置
break;
}
}
// 如果已经确定不能选,提前结束检查
if (!can_choose) break;
}
// 如果当前位置可以选取
if (can_choose) {
// 标记当前位置为已选取
used[x][y] = 1;
// 递归处理下一个位置,总和加上当前数字的值
solve(matrix, used, next_x, next_y, sum + matrix[x][y]);
// 回溯:取消当前位置的选取标记
used[x][y] = 0;
}
}
int main() {
int T;
scanf("%d", &T);
// 处理每组测试数据
while (T--) {
// 读取矩阵大小
scanf("%d %d", &N, &M);
int matrix[N][M]; // 存储数字矩阵
int used[N][M]; // 标记矩阵,记录哪些位置被选取
// 初始化used数组为0(所有位置都未选取)
memset(used, 0, sizeof(used));
// 读取数字矩阵
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
scanf("%d", &matrix[i][j]);
}
}
// 初始化最大结果为0
max_result = 0;
// 从矩阵的左上角(0,0)开始搜索
solve(matrix, used, 0, 0, 0);
// 输出最大和
printf("%d\n", max_result);
}
return 0;
} #include <iostream>
#include <vector>
#include <algorithm>
#include <array>
#include <utility>
using namespace std;
array<array<int, 6>, 6> grid;
array<array<bool, 6>, 6> selected;
int N, M, max_sum;
// 8个方向 (包含对角线)
const array<int, 8> DR = {-1, -1, -1, 0, 0, 1, 1, 1};
const array<int, 8> DC = {-1, 0, 1, -1, 1, -1, 0, 1};
int getnum();
void DFS(int r, int c, int cur_sum);
bool is_safe_to_choose(int r, int c);
// 检查 (r, c) 是否可以被选择
bool is_safe_to_choose(int r, int c) {
// 1. 检查 (r, c) 本身是否越界或已被选择
if (r >= N || r < 0 || c >= M || c < 0) return false;
for (int k = 0; k < 8; ++k) {
int pr = r + DR[k];
int pc = c + DC[k];
if (pr >= 0 && pr < N && pc >= 0 && pc < M) {
if (selected[pr][pc]) {
return false;
}
}
}
return true;
}
void DFS(int r, int c, int cur_sum) {
// 递归边界
if (r == N) {
// 所有格子已考虑完毕,更新最大和
max_sum = max(max_sum, cur_sum);
return;
}
int next_c = c + 1;
int next_r = r;
if (next_c == M) {
next_c = 0;
next_r = r + 1;
}
// 无论如何,我们都可以跳过当前格子
DFS(next_r, next_c, cur_sum);
// 必须确保选择是安全的,即周围 8 个格子没有被选择
if (is_safe_to_choose(r, c)) {
// 标记:选择当前格子
selected[r][c] = true;
// 递归:进入下一个格子
DFS(next_r, next_c, cur_sum + grid[r][c]);
// 回溯
selected[r][c] = false;
}
}
// 输入处理和结果输出
int getnum() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
selected[i][j] = false; // 初始化为未选择
}
}
max_sum = 0;
DFS(0, 0, 0);
return max_sum;
}
int main() {
int t;
if (!(cin >> t)) return 0;
while(t--){
cout << getnum() << "\n";
}
return 0;
}