奥赛一本通 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;
}
相关推荐
泯泷3 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
hold?fish:palm3 小时前
34 合并K个升序链表
javascript·算法·链表
Navigator_Z5 小时前
LeetCode //C - 1252. Cells with Odd Values in a Matrix
c语言·算法·leetcode
语戚7 小时前
力扣 1621. 大小为K的不重叠线段的数目:动态规划(Java 实现)
java·算法·leetcode·动态规划·力扣·dp
青山木7 小时前
Hot 100 --- 最长有效括号
java·数据结构·算法·leetcode·动态规划
这料鬼有毒8 小时前
二刷hot100-1143.最长公共子序列
算法·leetcode·动态规划
政企项目老覃9 小时前
边缘 AI 推理部署:安防零售场景下的模型裁剪与端侧落地实践
人工智能·程序人生·算法·性能优化·vllm
GreenTea11 小时前
发布 3 天登顶 HN:不生成一个字的模型 Jev,我把它的源码和黑料都扒了一遍
前端·后端·算法
庖丁解牛11 小时前
无穷小不是一个“神秘小数”,而是一场奔向 0 的过程
算法