博客
关于我
poj3074 DLX精确覆盖
阅读量:794 次
发布时间:2023-03-03

本文共 3542 字,大约阅读时间需要 11 分钟。

数独是一种经典的逻辑游戏,涉及到9x9的网格,每一行、每一列以及每个3x3的小九宫格都必须包含数字1到9。要解数独,需要仔细分析每个空格所在的行、列和小九宫格,找出可以填入的数字。以下是解数独的详细分析和方法:

数独的四个充要条件

  • 每个格子都有填数字:网格中的每一个空格都必须被填上数字。
  • 每列都有1~9中的每个数字:每一列必须包含从1到9的所有数字。
  • 每行都有1~9中的每个数字:每一行必须包含从1到9的所有数字。
  • 每个九宫格都有1~9中的每个数字:每个3x3的小九宫格必须包含从1到9的所有数字。
  • 转化为精确覆盖问题

    数独可以转化为精确覆盖问题。每行表示一个格子的一种填法,1~81表示这个格子的位置,82~162表示这是哪一行的什么数字,163~243表示这是哪一列的什么数字,244~324表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。

    解决方法

    对于已经确定的点,我们可以直接建一行。对于没有确定的点,我们可以建k行(k≤9),这样说如果在该行该列或者该3x3的矩阵中存在该数字,则对应的该数字所在的行就没有必要建立了。这样跑一次DLX精确覆盖就可以得到解。

    代码实现

    以下是基于DLX算法实现的数独解法代码:

    #include 
    #include
    #include
    #include
    #include
    using namespace std;struct node { int c, x, y, k;};struct DLX { int n, sz; int S[9*9*5]; int row[9*9*4], col[9*9*4]; int L[9*9*4], R[9*9*4], U[9*9*4], D[9*9*4]; int ans[10][10]; int X[9*9*4], Y[9*9*4], Cnt[9*9*4]; void init(int n) { this->n = n; sz = n + 1; for (int i = 0; i <= n; ++i) { U[i] = i; D[i] = i; L[i] = i - 1; R[i] = i + 1; } R[n] = 0; L[0] = n; sz = n + 1; memset(S, 0, sizeof(S)); } void addRow(int r, vector
    colums) { int first = sz; for (int i = 0; i < colums.size(); ++i) { int c = colums[i].c; int x = colums[i].x; int y = colums[i].y; int cnt = colums[i].k; row[sz] = r; col[sz] = c; L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = colums[i].d; U[D[sz]] = sz; sz++; } r[sz - 1] = first; L[first] = sz - 1; sz++; } void remove(int c) { L[r[c]] = c; R[L[c]] = c; for (int i = D[c]; i != 0; ++i) { int j = U[i]; D[U[j]] = D[j]; --S[col[j]]; } } bool dfs(int d) { if (r[0] == 0) return true; else { int num = R[0]; for (int i = D[0]; i != 0; ++i) { if (S[col[i]] == 0) { num = i; break; } } if (num == 0) return false; if (S[col[num]] > 0) return false; S[col[num]]++; for (int i = D[num]; i != 0; ++i) { int j = U[i]; D[U[j]] = D[j]; --S[col[j]]; } if (dfs(num + 1)) return true; for (int i = L[num]; i != 0; ++i) { int j = col[i]; restore(j); } restore(num); return false; } }};bool hasr[10][10], hasc[10][10], hasp[10][10];char str[100];vector
    colum;int main() { while (scanf("%s", str) == 1 && str[0] != 'e') { memset(hasp, false, sizeof(hasp)); for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (str[i * 9 + j] != '.') { int k = str[i * 9 + j] - '0'; hasr[i][k] = true; hasc[j][k] = true; hasp[i / 3 * 3 + j / 3][k] = true; } } } DLX Link; Link.init(324); colum.clear(); for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (str[i * 9 + j] != '.') { int k = str[i * 9 + j] - '0'; node dot; dot.k = k; dot.x = i; dot.y = j; dot.c = i * 9 + j + 1; colum.push_back(dot); dot.c = 81 + i * 9 + k; colum.push_back(dot); dot.c = 162 + j * 9 + k; colum.push_back(dot); dot.c = 243 + (i / 3 * 3 + j / 3) * 9 + k; colum.push_back(dot); Link.addRow(0, colum); } else { node dot; dot.x = i; dot.y = j; for (int k = 1; k <= 9; ++k) { if (!hasr[i][k] || !hasc[j][k] || !hasp[i / 3 * 3 + j / 3][k]) { node dot; dot.k = k; colum.clear(); dot.c = i * 9 + j + 1; colum.push_back(dot); dot.c = 81 + i * 9 + k; colum.push_back(dot); dot.c = 162 + j * 9 + k; colum.push_back(dot); dot.c = 243 + (i / 3 * 3 + j / 3) * 9 + k; colum.push_back(dot); Link.addRow(0, colum); } } } } } if (Link.dfs(0)) { for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { printf("%d", Link.ans[i][j]); puts(""); } } } } return 0;}

    总结

    通过以上方法,我们可以高效地解数独问题。代码实现了DLX算法,能够处理复杂的精确覆盖问题,确保了数独的正确解。通过对已知数字的处理和对未知数字的尝试,结合DLX算法的强大能力,可以轻松解决数独难题。

    转载地址:http://wcxfk.baihongyu.com/

    你可能感兴趣的文章
    PHP获取当前时间、时间戳的各种格式写法汇总
    查看>>
    PHP获取当前页面的完整URL
    查看>>
    php获取文件夹中文件的两种方法
    查看>>
    PHP获取日期的一些方法总结
    查看>>
    R2学习记录
    查看>>
    php解析ipa包,获取logo
    查看>>
    php设计模式 萨莱 pdf,PHP设计模式 建造者模式
    查看>>
    php设计模式之装饰器模式
    查看>>
    R&Python Data Science系列:数据处理(5)--字符串函数基于R(一)
    查看>>
    PHP设计模式:观察者模式
    查看>>
    php详细学习1
    查看>>
    php语言优劣
    查看>>
    PHP语言最优雅的支付SDK扩展包
    查看>>
    PHP请求https域名发生segment fault段错误
    查看>>
    PHP读写XML文件
    查看>>
    PHP读写XML文件
    查看>>
    R&Python Data Science 系列:数据处理(3)
    查看>>
    php读取xml 数据库字段超长处理
    查看>>
    php课程 12-40 抽象类的作用是什么
    查看>>
    php课程 4-16 数组自定义函数(php数组->桶)
    查看>>