首页 > 试题广场 >

取数游戏

[编程题]取数游戏
  • 热度指数:2307 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
{\hspace{15pt}}一个 N\times M 的由非负整数构成的数字矩阵,你需要在其中取出若干个数字,使得取出的任意两个数字不相邻(若一个数字在另外一个数字相邻 8 个格子中的一个即认为这两个数字相邻),求取出数字和最大是多少。

输入描述:
{\hspace{15pt}}第一行有一个正整数 T1\leqq T\leqq 20,表示了有 T 组数据。

{\hspace{15pt}}对于每一组数据,第一行有两个正整数 N,M1\leqq N, M\leqq 6,表示了数字矩阵为 N 行 M 列。

{\hspace{15pt}}接下来 N 行,每行 M 个非负整数,描述了这个数字矩阵,满足 1 \leqq a_{i,j}\leqq 10^5


输出描述:
{\hspace{15pt}}输出共 T 行,每行一个非负整数,输出所求得的答案。
示例1

输入

1
3 3
1 1 1
1 1 1
1 1 1

输出

4
AI太强了,下面是deepseek写出的代码,程序员可以失业了。
#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;
}


发表于 2025-10-16 16:54:02 回复(1)
#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;
}

发表于 2025-10-26 14:17:04 回复(0)