LA 2659 poj 3076 zoj 3122 Sudoku(精确覆盖 + DLX)
題目鏈接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=660
TimeLimit: 3.000 seconds
A Sudoku grid is a?16?x?16?grid of cells grouped in sixteen?4?x?4?squares, where some cells are filled with letters from?A?to?P?(the first 16 capital letters of the English alphabet), as shown in figure 1a. The game is to fill all the empty grid cells with letters from?A?to?P?such that each letter from the grid occurs once only in the line, the column, and the?4?x?4?square it occupies. The initial content of the grid satisfies the constraints mentioned above and guarantees a unique solution.
Figure 1. Sudoku
| ? | ? | A | ? | ? | ? | ? | C | ? | ? | ? | ? | ? | O | ? | I |
| ? | J | ? | ? | A | ? | B | ? | P | ? | C | G | F | ? | H | ? |
| ? | ? | D | ? | ? | F | ? | I | ? | E | ? | ? | ? | ? | P | ? |
| ? | G | ? | E | L | ? | H | ? | ? | ? | ? | M | ? | J | ? | ? |
| ? | ? | ? | ? | E | ? | ? | ? | ? | C | ? | ? | G | ? | ? | ? |
| ? | I | ? | ? | K | ? | G | A | ? | B | ? | ? | ? | E | ? | J |
| D | ? | G | P | ? | ? | J | ? | F | ? | ? | ? | ? | A | ? | ? |
| ? | E | ? | ? | ? | C | ? | B | ? | ? | D | P | ? | ? | O | ? |
| E | ? | ? | F | ? | M | ? | ? | D | ? | ? | L | ? | K | ? | A |
| ? | C | ? | ? | ? | ? | ? | ? | ? | ? | O | ? | I | ? | L | ? |
| H | ? | P | ? | C | ? | ? | F | ? | A | ? | ? | B | ? | ? | ? |
| ? | ? | ? | G | ? | O | D | ? | ? | ? | J | ? | ? | ? | ? | H |
| K | ? | ? | ? | J | ? | ? | ? | ? | H | ? | A | ? | P | ? | L |
| ? | ? | B | ? | ? | P | ? | ? | E | ? | ? | K | ? | ? | A | ? |
| ? | H | ? | ? | B | ? | ? | K | ? | ? | F | I | ? | C | ? | ? |
| ? | ? | F | ? | ? | ? | C | ? | ? | D | ? | ? | H | ? | N | ? |
| ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
| F | P | A | H | M | J | E | C | N | L | B | D | K | O | G | I |
| O | J | M | I | A | N | B | D | P | K | C | G | F | L | H | E |
| L | N | D | K | G | F | O | I | J | E | A | H | M | B | P | C |
| B | G | C | E | L | K | H | P | O | F | I | M | A | J | D | N |
| M | F | H | B | E | L | P | O | A | C | K | J | G | N | I | D |
| C | I | L | N | K | D | G | A | H | B | M | O | P | E | F | J |
| D | O | G | P | I | H | J | M | F | N | L | E | C | A | K | B |
| J | E | K | A | F | C | N | B | G | I | D | P | L | H | O | M |
| E | B | O | F | P | M | I | J | D | G | H | L | N | K | C | A |
| N | C | J | D | H | B | A | E | K | M | O | F | I | G | L | P |
| H | M | P | L | C | G | K | F | I | A | E | N | B | D | J | O |
| A | K | I | G | N | O | D | L | B | P | J | C | E | F | M | H |
| K | D | E | M | J | I | F | N | C | H | G | A | O | P | B | L |
| G | L | B | C | D | P | M | H | E | O | N | K | J | I | A | F |
| P | H | N | O | B | A | L | K | M | J | F | I | D | C | E | G |
| I | A | F | J | O | E | C | G | L | D | P | B | H | M | N | K |
| ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
Write a Sudoku playing program that reads data sets from a text file.
Input?
Each data set encodes a grid and contains 16 strings on 16 consecutive lines as shown in figure 2. The?i-th string stands for the?i-th line of the grid, is 16 characters long, and starts from the first position of the line. String characters are from the set?{A,B,...,P,-}, where `-' (minus) designates empty grid cells. The data sets are separated by single empty lines and terminate with an end of file.
Output?
The program prints the solution of the input encoded grids in the same format and order as used for input.
Sample Input?
--A----C-----O-I -J--A-B-P-CGF-H- --D--F-I-E----P- -G-EL-H----M-J-- ----E----C--G--- -I--K-GA-B---E-J D-GP--J-F----A-- -E---C-B--DP--O- E--F-M--D--L-K-A -C--------O-I-L- H-P-C--F-A--B--- ---G-OD---J----H K---J----H-A-P-L --B--P--E--K--A- -H--B--K--FI-C-- --F---C--D--H-N-Sample Output?
FPAHMJECNLBDKOGI OJMIANBDPKCGFLHE LNDKGFOIJEAHMBPC BGCELKHPOFIMAJDN MFHBELPOACKJGNID CILNKDGAHBMOPEFJ DOGPIHJMFNLECAKB JEKAFCNBGIDPLHOM EBOFPMIJDGHLNKCA NCJDHBAEKMOFIGLP HMPLCGKFIAENBDJO AKIGNODLBPJCEFMH KDEMJIFNCHGAOPBL GLBCDPMHEONKJIAF PHNOBALKMJFIDCEG IAFJOECGLDPBHMNK
1.每行A~P恰好各出現一次
2.每列A~P恰好各出現一次
3.粗線分隔出的每個4*4子方陣(一共有4*4個)中,A~P恰好各出現一次。
分析:直接套DLX
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std;const int maxn = 1024 + 10; const int maxr = 4096 + 10; const int maxnode = maxr * 4 + maxn;// 行編號從1開始,列編號為1~n,結點0是表頭結點,節點1~n是各列頂部的虛擬結點 struct DLX {int n, sz; // 列數,結點總數int S[maxn]; // 各列結點數int row[maxnode], col[maxnode]; // 各結點行列編號int L[maxnode], R[maxnode], U[maxnode], D[maxnode]; // 十字鏈表int ansd, ans[maxr]; // 解void init(int n) { // n是列數this->n = n;// 虛擬結點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<int> columns) {int first = sz;for(int i = 0; i < columns.size(); i++) {int c = columns[i];L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];D[U[c]] = sz; U[c] = sz;row[sz] = r; col[sz] = c;S[c]++; sz++;}R[sz-1] = first; L[first] = sz - 1;}// 順著鏈表,遍歷除s外的其他元素 #define FOR(i, A, s) for(int i = A[s]; i != s; i = A[i])void remove(int c) {L[R[c]] = L[c];R[L[c]] = R[c];for(int i = D[c]; i != c; i = D[i])for(int j = R[i]; j != i; j = R[j]) {U[D[j]] = U[j];D[U[j]] = D[j];--S[col[j]];}}void restore(int c) {for(int i = U[c]; i != c; i = U[i])for(int j = L[i]; j != i; j = L[j]) {++S[col[j]];U[D[j]] = j;D[U[j]] = j;}L[R[c]] = c;R[L[c]] = c;}// d為遞歸深度bool dfs(int d) {if(R[0] == 0) { // 找到解ansd = d; // 記錄解的長度return true;}int c = R[0]; //第一個未刪除的列for(int i = R[0]; i != 0; i = R[i])if(S[i] < S[c]) c = i;remove(c); // 刪除第c列for(int i = D[c]; i != c; i = D[i]) { // 用結點i所在行覆蓋第c列ans[d] = row[i];for(int j = R[i]; j != i; j = R[j]) remove(col[j]); // 刪除結點i所在行能覆蓋的所有其他列if(dfs(d + 1)) return true;for(int j = L[i]; j != i; j = L[j]) restore(col[j]); // 恢復結點i所在行能覆蓋的所有其他列}restore(c); // 恢復第c列return false;}bool solve(vector<int> &v) {v.clear();if(!dfs(0)) return false;for(int i = 0; i < ansd; i++) v.push_back(ans[i]);return true;} };DLX solver;const int SLOT = 0; const int ROW = 1; const int COL = 2; const int SUB = 3;// 行/列的統一編解碼函數,從1開始編號 inline int encode(int a, int b, int c) {return a * 256 + b * 16 + c + 1; }void decode(int code, int &a, int &b, int &c) {code--;c = code % 16; code /= 16;b = code % 16; code /= 16;a = code; }char puzzle[16][20];bool read() {for(int i = 0; i < 16; i++)if(scanf("%s", puzzle[i]) == EOF) return false;return true; }int main() {int kase = 0;while(read()) {if(++kase != 1) printf("\n");solver.init(1024);for(int r = 0; r < 16; r++)for(int c = 0; c < 16; c++)for(int v = 0; v < 16; v++)if(puzzle[r][c] == '-' || puzzle[r][c] == 'A' + v) {vector<int> columns;columns.push_back(encode(SLOT, r, c));columns.push_back(encode(ROW, r, v));columns.push_back(encode(COL, c, v));columns.push_back(encode(SUB, (r/4)*4+c/4, v));solver.addRow(encode(r, c, v), columns);}vector<int> ans;solver.solve(ans);for(int i = 0; i < ans.size(); i++) {int r, c, v;decode(ans[i], r, c, v);puzzle[r][c] = 'A' + v;}for(int i = 0; i < 16; i++)printf("%s\n", puzzle[i]);}return 0; }與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
以上是生活随笔為你收集整理的LA 2659 poj 3076 zoj 3122 Sudoku(精确覆盖 + DLX)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我说我了解集合类,面试官竟然问我为啥Ha
- 下一篇: Arthas - Java 线上问题定位