「NOIP2009」靶形数独

倾然丶 夕夏残阳落幕 提交于 2019-12-02 16:08:43

传送门
Luogu

解题思路

这题其实挺简单的。
首先要熟悉数独,我们应该要优先搜索限制条件多的行,也就是可能方案少的行,显然这样可以剪枝,然后再发挥一下dfs的基本功就可以了。

细节注意事项

  • 爆搜题,你们都懂。。。

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    s = f ? -s : s;
}

const int s[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 }
};

const int p[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 },   
};

struct node { int id, cnt; }a[10];
inline bool cmp(const node& x, const node& y) { return x.cnt > y.cnt; }
int ans = -1, mp[10][10]; bool Line[10][10], Clmn[10][10], Palc[10][10];

inline void dfs(int i, int j, int line, int sum) {
    if (line > 9) { ans = max(ans, sum); return; }
    if (j == 10) { dfs(a[line + 1].id, 1, line + 1, sum); return ; }
    if (mp[i][j]) { dfs(i, j + 1, line, sum); return; }
    for (rg int x = 1; x <= 9; ++x) {
        if (Line[i][x]) continue;
        if (Clmn[j][x]) continue;
        if (Palc[p[i][j]][x]) continue;
        Line[i][x] = Clmn[j][x] = Palc[p[i][j]][x] = 1, mp[i][j] = x;
        dfs(i, j + 1, line, sum + x * s[i][j]);
        Line[i][x] = Clmn[j][x] = Palc[p[i][j]][x] = 0, mp[i][j] = 0;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
#endif
    for (rg int i = 1; i <= 9; ++i) a[i].id = i;
    int tmp = 0;
    for (rg int i = 1; i <= 9; ++i)
        for (rg int j = 1; j <= 9; ++j) {
            int x; read(x), mp[i][j] = x;
            if (x) Line[i][x] = 1, Clmn[j][x] = 1, Palc[p[i][j]][x] = 1, ++a[i].cnt, tmp += x * s[i][j];
        }
    sort(a + 1, a + 10, cmp);
    dfs(a[1].id, 1, 0, tmp);
    printf("%d\n", ans);
    return 0;
}

完结撒花 \(qwq\)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!