UVALive 2659 数独 DLX模板

建图:

  从1到16枚举所有的行、列上放的数。

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <queue>
  9 #include <stack>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <functional>
 14 #include <cctype>
 15 #include <time.h>
 16
 17 using namespace std;
 18
 19 const int INF = 1<<30;
 20 const int MAXN = 1055;
 21 const int MAXNODE = 16555;
 22 const int MAXR = 1055;
 23
 24 struct DLX {
 25 // 行编号从1开始,列编号为1~n,结点0是表头结点;结点1~n是各列顶部的虚拟结点
 26     int n, sz; // 列数,结点总数
 27     int S[MAXN]; //各列结点数
 28
 29     int row[MAXNODE], col[MAXNODE]; //各结点行列编号
 30     int L[MAXNODE], R[MAXNODE], U[MAXNODE], D[MAXNODE]; //十字链表
 31
 32     int ansd, ans[MAXR]; // 解
 33
 34     void init(int n)  { //n是列数
 35         this->n = n;
 36
 37         //虚拟结点
 38         for (int i = 0; i <= n; i++) {
 39             U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;
 40         }
 41         R[n] = 0; L[0] = n;
 42         sz = n+1;
 43         memset(S, 0, sizeof(S));
 44     }
 45
 46     void addRow(int r, vector<int> columns) {
 47         //这一行的第一个结点
 48         //行没有设头结点,每一行连成一个环形
 49         int first = sz;
 50         for (int i = 0; i < columns.size(); i++) {
 51             int c = columns[i];
 52             L[sz] = sz-1; R[sz] = sz+1; D[sz] = c; U[sz] = U[c];
 53             D[U[c]] = sz; U[c] = sz;
 54             row[sz] = r; col[sz] = c;
 55             S[c]++; sz++;
 56         }
 57         R[sz-1] = first; L[first] = sz-1;
 58     }
 59
 60     //顺着链表A,遍历s外的其他元素
 61     #define FOR(i, A, s) for (int i = A[s]; i != s; i = A[i])
 62
 63     void remove(int c) { //删除c列
 64         L[R[c]] = L[c]; R[L[c]] = R[c];
 65         for (int i = D[c]; i != c; i = D[i]) // 对于每一个c列不为0的所有行
 66             for (int j = R[i]; j != i; j = R[j]) { //删除这一整行
 67                 U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]]--;
 68             }
 69     }
 70
 71     void restore(int c) { //回连c列
 72         for (int i = U[c]; i != c; i = U[i])
 73             for (int j = L[i]; j != i; j = L[j]) {
 74                 U[D[j]] = j; D[U[j]] = j; S[col[j]]++;
 75             }
 76         L[R[c]] = c; R[L[c]] = c;
 77     }
 78
 79     bool dfs(int d) { //d为递归深度
 80         if (R[0] == 0) { //找到解
 81             ansd = d; //记录解的长度
 82             return true;
 83         }
 84
 85         //找S最小的C列
 86         int c = R[0]; //第一个未删除的列
 87         for (int i = R[0]; i != 0; i = R[i]) if (S[i]<S[c]) c = i;
 88
 89         remove(c); //删除第c列
 90         for (int i = D[c]; i != c; i = D[i]) { //用结点i所在的行覆盖第c列
 91             ans[d] = row[i];
 92             for (int j = R[i]; j != i; j = R[j]) remove(col[j]); //删除节结点i所在行覆盖第c列
 93             if (dfs(d+1)) return true;
 94             for (int j = L[i]; j != i; j = L[j]) restore(col[j]); // 恢复
 95         }
 96         restore(c); //恢复
 97         return false;
 98     }
 99
100     bool solve(vector<int> &v) {
101         v.clear();
102         if(!dfs(0)) return false;
103         for (int i = 0; i < ansd; i++) v.push_back(ans[i]);
104         return true;
105     }
106 };
107
108 const int SLOT = 0;
109 const int ROW = 1;
110 const int COL = 2;
111 const int SUB = 3;
112
113 inline int encode(int a, int b, int c) {
114     return a*256 + b*16 + c + 1;
115 }
116
117 inline void decode(int code, int &a, int &b, int &c) {
118     code--;
119     c = code%16; code /= 16;
120     b = code%16; code /= 16;
121     a = code;
122 }
123
124 char puzzle[16][20];
125
126 bool read() {
127     for (int i = 0; i < 16; i++)
128         if (scanf("%s", puzzle[i])!=1) return false;
129     return true;
130 }
131
132 DLX solver;
133
134 int main() {
135     #ifdef Phantom01
136         freopen("LA2659.txt", "r", stdin);
137     #endif //Phantom01
138
139     int T= 0;
140
141     while (read()) {
142         if (T!=0) puts(""); T++;
143         solver.init(1024);
144         for (int r = 0; r < 16; r++)
145             for (int c = 0; c < 16; c++)
146                 for (int v = 0; v < 16; v++)
147                     if (puzzle[r][c]==‘-‘|| puzzle[r][c]==‘A‘+v) {
148                         vector<int> columns;
149                         columns.push_back(encode(SLOT, r, c));
150                         columns.push_back(encode(ROW, r, v));
151                         columns.push_back(encode(COL, c, v));
152                         columns.push_back(encode(SUB, (r/4)*4+c/4, v));
153                         solver.addRow(encode(r, c, v), columns);
154                     }
155         vector<int> ans;
156         if (!solver.solve(ans)) while (1) ;
157
158         for (int i = 0; i < ans.size(); i++) {
159             int r, c, v;
160             decode(ans[i], r, c, v);
161             puzzle[r][c] = ‘A‘+v;
162         }
163         for (int i = 0; i < 16; i++) {
164             printf("%s\n", puzzle[i]);
165         }
166     }
167
168     return 0;
169 }

时间: 2024-08-04 18:39:09

UVALive 2659 数独 DLX模板的相关文章

UVALive 2659+HUST 1017+ZOJ 3209 (DLX

UVALive 2659 题目:16*16的数独.试了一发大白模板. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include

[ACM] POJ 3740 Easy Finding (DLX模板题)

Easy Finding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16178   Accepted: 4343 Description Given a M×N matrix A. Aij ∈ {0, 1} (0 ≤ i < M, 0 ≤ j < N), could you find some rows that let every cloumn contains and only contains one 1.

POJ 3076 数独DLX

Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4203   Accepted: 2051 Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the first 16 capital l

最新版dlx模板(精确覆盖+重复覆盖)

以前的代码太挫了,重新整理dlx,学习HH把精确覆盖,重复覆盖整合在一起. 代码: struct DLX{ const static int maxn=20010; #define FF(i,A,s) for(int i = A[s];i != s;i = A[i]) int L[maxn],R[maxn],U[maxn],D[maxn]; int size,col[maxn],row[maxn],s[maxn],H[maxn]; bool vis[70]; int ans[maxn],cnt;

【NOIP2009】靶形数独 DLX(Dancing Links)

[NOIP2009]靶形数独 T4 Time Limit: 2 Sec  Memory Limit: 128 MB Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z 博士请教,Z 博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在

DLX模板

1 const int maxnode=100010; 2 const int maxn=1010; 3 const int maxm=1010; 4 struct DLX 5 { 6 int L[maxnode],R[maxnode],U[maxnode],D[maxnode],Row[maxnode],Col[maxnode],C[maxm],H[maxn],cnt; 7 int ans[maxn],ansd; 8 void Init(int n,int m) 9 { 10 for(int

Poj3074-Sudoku(数独DLX)

题意: 给出一个9*9的矩阵,有一些格子已经填了数,有一些是.代表未填.求任意一组解使得每行包含1~9,每列包含1~9,每个小矩形(3*3)包含1~9. 解析: 精确覆盖DLX的经典题目,每一行代表要填数的情况,列共有81*4行,第一个81行代表第i行j列放了数,第二个81列代表第i行放的数k,第三个81列 代表第j列放得数k,第四个81行代表第i个小矩形放的数k.对于字符为.的情况添加9行,对于字符为数字的情况添加一行.然后就是跑一边DLX,保存一下答案 输出即可. 代码 #include<c

POJ 3076 数独(DLX算法)

Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4439   Accepted: 2160 Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the first 16 capital l

hihoCoder #1321 : 搜索五?数独 (Dancing Links ,精确覆盖)

hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. 提示已经讲解的很清楚了.稍微整理下思路.最后附AC代码. 一.Dancing Links解决精确覆盖问题.      1.精确覆盖问题         给定一个n行,m列的01矩阵.从中选择若干行使得每一列有且恰好只有一个1. 例如: 答案是选择2,3,4行. 2.DancingLinks求解精确