奥赛一本通 1447 靶形数独

1447 靶形数独

题目大意

需要完成一个数独,不过每个格子都有一个分值,最终的得分为每个格子的分值与填在相应格上数字的乘积之和,求最大得分。

知识要点

搜索、剪枝

解题思路

使用二维数组存储每个格子所在的九宫格编号,为每行每列每个九宫格中已经出现的数字打标记,搜索时应该先确定当前可填数字方案数最少的格子。

参考代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int point[10][10] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    0, 6, 7, 7, 7, 7, 7, 7, 7, 6,
    0, 6, 7, 8, 8, 8, 8, 8, 7, 6,
    0, 6, 7, 8, 9, 9, 9, 8, 7, 6,
    0, 6, 7, 8, 9, 10, 9, 8, 7, 6,
    0, 6, 7, 8, 9, 9, 9, 8, 7, 6,
    0, 6, 7, 8, 8, 8, 8, 8, 7, 6,
    0, 6, 7, 7, 7, 7, 7, 7, 7, 6,
    0, 6, 6, 6, 6, 6, 6, 6, 6, 6
};
int gong[10][10] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
    0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
    0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
    0, 4, 4, 4, 5, 5, 5, 6, 6, 6,
    0, 4, 4, 4, 5, 5, 5, 6, 6, 6,
    0, 4, 4, 4, 5, 5, 5, 6, 6, 6,
    0, 7, 7, 7, 8, 8, 8, 9, 9, 9,
    0, 7, 7, 7, 8, 8, 8, 9, 9, 9,
    0, 7, 7, 7, 8, 8, 8, 9, 9, 9
};
int n, ans = -1;
bool h[10][10], l[10][10], g[10][10]; //行列九宫格标记
struct {
    int x, y, v;
} P[100]; //待填格子

void DFS(int d, int sum) {
    if(d == n) {
        if(ans < sum) ans = sum;
        return;
    }

    int t = 10, k, x, y, c; //找可填数字方案数最少的格子
    for(int i = 0; i < n; i++) {
        if(P[i].v) continue;
        x = P[i].x, y = P[i].y, c = 0;
        for(int j = 1; j <= 9; j++) if(!h[x][j] && !l[y][j] && !g[gong[x][y]][j]) c++;
        if(t > c) t = c, k = i;
    }

    x = P[k].x, y = P[k].y, c = gong[x][y];
    P[k].v = 1; //标记已填
    for(int j = 1; j <= 9; j++) if(!h[x][j] && !l[y][j] && !g[c][j]) {
        h[x][j] = l[y][j] = g[c][j] = 1;
        DFS(d + 1, sum + j * point[x][y]);
        h[x][j] = l[y][j] = g[c][j] = 0;
    }
    P[k].v = 0; //恢复未填
}
int main() {
    int t, sum = 0;
    for(int i = 1; i <= 9; i++) for(int j = 1; j <= 9; j++) {
        scanf("%d", &t);
        if(!t) P[n++] = {i, j, 0}; //存储待填格子
        else h[i][t] = l[j][t] = g[gong[i][j]][t] = 1, sum += t * point[i][j];
    }

    DFS(0, sum);
    printf("%d\n", ans);
    return 0;
}
相关推荐
Nil20817 小时前
leetcode 118杨辉三角
算法·leetcode·职场和发展
wanderist.19 小时前
线性筛法详解:从筛质数到欧拉函数、Möbius 函数与约数函数
java·数据结构·算法
All for pursuit.19 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
weixin_3077791319 小时前
C++代码实现MATLAB中的crossval函数功能
开发语言·c++·算法·matlab
青少儿编程课堂19 小时前
背包问题(0/1 背包与完全背包)解题精讲——动态规划入门
c++·python·算法·bfs·信息学竞赛
光影少年20 小时前
为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?
前端·javascript·算法
HEJOO920 小时前
Linux 设备驱动系列——使用全局工作队列
java·linux·算法
Code_Solitude20 小时前
c语言:递归
java·c语言·算法
edtoplort21 小时前
OpenAI紧急叫停GPT-6.1 Astra训练,奥尔特曼为何踩刹车
人工智能·gpt·算法
蒜香可达鸭21 小时前
让视频生成流水线跑不崩:一个事件溯源的多 Agent 可靠执行框架
算法