HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
来源:互联网 发布:直播平台系统源码 编辑:程序博客网 时间:2024/05/29 10:19
题目地址
题意:给你一个数独残图,问你是不是能求出完整的图,完整的数独是什么样子的(唯一)。
思路:数独的限制条件就是4个,分别是
- 位置限制:每一格有且仅有一个数
- 列限制:每一列中每个数仅出现一次
- 行限制:每一行中每个数仅出现一次
- 区域限制:每个区域每个数仅出现一次
所以我们创建的矩阵要满足这些条件,所以我们划分出行的区间来表示这些限制条件
- 1-81行表示的是位置限制
- 82-162行表示的是列限制
- 163-243行表示的是行限制
- 244-324行表示的是区域限制
然后每一列表示的是该位置数的情况,比如mat[i][j]=2的话,那么(i*9+j)*9+2列的某些行(对应限制行)就为1,当如果是不确定的话(为没有填写的),那么就是把可以填的数字全部的列的某些行的值为1就好了,然后求一遍DLX的精确覆盖。
推荐知乎上一篇讲数独求解该怎样转化为精确覆盖问题:传送门
#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 110#define MAXSIZE 1010*1010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1 using namespace std;const LL mod = 1000000007;struct node { int left, right, up, down, col, row;}mapp[MAXSIZE];int S[MAXSIZE], H[MAXSIZE];//S记录该列中1元素的个数int head, cnt;int ans[N];int len;struct Dancing_Links_X { void init(int m) { head = 0; for (int i = 0; i <= m; i++) { S[i] = 0; mapp[i].up = mapp[i].down = i; mapp[i].left = (i == 0 ? m : i - 1); mapp[i].right = (i == m ? 0 : i + 1); } cnt = m; memset(H, -1, sizeof(H)); } void link(int x, int y) { cnt++; mapp[cnt].row = x; mapp[cnt].col = y; S[y]++; mapp[cnt].up = mapp[y].up; mapp[cnt].down = y; mapp[mapp[y].up].down = cnt; mapp[y].up = cnt; if (H[x] == -1) H[x] = mapp[cnt].left = mapp[cnt].right = cnt; else { mapp[cnt].left = mapp[H[x]].left; mapp[cnt].right = H[x]; mapp[mapp[H[x]].left].right = cnt; mapp[H[x]].left = cnt; } } void remove(int c) {//删去c这个点,以及关联的一列 mapp[mapp[c].right].left = mapp[c].left; mapp[mapp[c].left].right = mapp[c].right; for (int i = mapp[c].down; i != c; i = mapp[i].down) { for (int j = mapp[i].right; j != i; j = mapp[j].right) { mapp[mapp[j].down].up = mapp[j].up; mapp[mapp[j].up].down = mapp[j].down; --S[mapp[j].col]; } } } void resume(int c) {//恢复c这个点,以及关联的一列 for (int i = mapp[c].up; i != c; i = mapp[i].up) { for (int j = mapp[i].left; j != i; j = mapp[j].left) { ++S[mapp[j].col]; mapp[mapp[j].down].up = mapp[mapp[j].up].down = j; } } mapp[mapp[c].right].left = mapp[mapp[c].left].right = c; } bool dance(int k) { if (mapp[head].right == head) { len = k; //cout << endl << len << endl << endl; return true; } int s = inf, c; for (int t = mapp[head].right; t != head; t = mapp[t].right) { if (S[t] < s) s = S[t], c = t; } remove(c); for (int i = mapp[c].down; i != c; i = mapp[i].down) { ans[k] = mapp[i].row; for (int j = mapp[i].right; j != i; j = mapp[j].right) { remove(mapp[j].col); } if (dance(k + 1)) { return true; } for (int j = mapp[i].left; j != i; j = mapp[j].left) { resume(mapp[j].col); } } resume(c); return false; }}DLX;int main() { cin.sync_with_stdio(false); int n, m; char mat[N][N]; int T; cin >> T; while (T--) { n = 9 * 9 * 9;//行 m = 9 * 9 * 4;//列 DLX.init(m); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { cin >> mat[i][j]; } } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (mat[i][j] != '0') { int r = (i * 9 + j) * 9 + mat[i][j] - '0'; int c1 = i * 9 + j + 1; int c2 = 81 + i * 9 + mat[i][j] - '0'; int c3 = 162 + j * 9 + mat[i][j] - '0'; int c4 = 243 + (i / 3 * 3 + j / 3) * 9 + mat[i][j] - '0'; DLX.link(r, c1); DLX.link(r, c2); DLX.link(r, c3); DLX.link(r, c4); S[c1] = S[c2] = S[c3] = S[c4] = -1; } } } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (mat[i][j] == '0') { for (int k = 1; k <= 9; k++) { int r = (i * 9 + j) * 9 + k; int c1 = i * 9 + j + 1; int c2 = 81 + i * 9 + k; int c3 = 162 + j * 9 + k; int c4 = 243 + (i / 3 * 3 + j / 3) * 9 + k; if (~S[c1] && ~S[c2] && ~S[c3] && ~S[c4]) { DLX.link(r, c1); DLX.link(r, c2); DLX.link(r, c3); DLX.link(r, c4); } } } } } len = inf; if (DLX.dance(0)) { for (int i = 0; i < len; i++) { int Orz = (ans[i] - 1) % 9 + 1; int x = (ans[i] - 1) / 9 / 9; int y = (ans[i] - 1) / 9 % 9; mat[x][y] = Orz + '0'; } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { cout << mat[i][j]; } cout << endl; } } else { cout << "Could not complete this grid." << endl; } if (T) { cout << endl; } } return 0;}
阅读全文
0 0
- HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
- 【HDU】2780 Su-Su-Sudoku【数独】精确覆盖
- [DLX精确覆盖] hdu 4210 Su-domino-ku
- hdu 2780 Su-Su-Sudoku(DFS数独)
- 【DFS】hdu 2780 Su-Su-Sudoku
- HDU 3909 Sudoku(数独转DLX精确覆盖)
- HDU 4069 Squiggly Sudoku DLX 精确覆盖
- POJ 3074 Sudoku(DLX+精确覆盖)
- DLX精确覆盖 poj2676 Sudoku
- hdu 2780 Su-Su-Sudoku (dfs解的数独)
- poj 3074 Sudoku (精确覆盖,DLX,搜索)
- DLX(精确覆盖) POJ 3074 Sudoku
- POJ 3074 Sudoku DLX精确覆盖
- POJ 3076 Sudoku DLX精确覆盖
- DLX精确覆盖 hdu4069 Squiggly Sudoku
- POJ 3076 Sudoku 精确覆盖问题DLX
- DLX算法求解精确覆盖问题
- soj 1664. Su-Su-Sudoku
- 01-复杂度2 Maximum Subsequence Sum(25 分)
- git stash 恢复
- spring-retry注解方式使用(断路器,重试)
- 关于制作游戏中产生的子弹方向问题的思考
- 【20171003】python_语言设计(5)字典
- HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
- Linux常用命令总结
- linux下编译安装boost库
- 使用python统计csdn博客一段时间内的访问量
- C语言 动态一维数组
- Image Processing——图像处理教程(二)之MATLAB基础
- Physics Simulation
- Scala(4)-通过mixin实现类合成
- Intellij IDEA 启动项目ClassNotFoundException