第一行有一个正整数
(
),表示了有
组数据。
对于每一组数据,第一行有两个正整数
(
),表示了数字矩阵为
行
列。
接下来
行,每行
个非负整数,描述了这个数字矩阵,满足
。
输出共
行,每行一个非负整数,输出所求得的答案。
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;
}