日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

LA 2659 poj 3076 zoj 3122 Sudoku(精确覆盖 + DLX)

發布時間:2025/3/16 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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?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?
????????????????

a) Sudoku grid


FPAHMJECNLBDKOGI
OJMIANBDPKCGFLHE
LNDKGFOIJEAHMBPC
BGCELKHPOFIMAJDN
MFHBELPOACKJGNID
CILNKDGAHBMOPEFJ
DOGPIHJMFNLECAKB
JEKAFCNBGIDPLHOM
EBOFPMIJDGHLNKCA
NCJDHBAEKMOFIGLP
HMPLCGKFIAENBDJO
AKIGNODLBPJCEFMH
KDEMJIFNCHGAOPBL
GLBCDPMHEONKJIAF
PHNOBALKMJFIDCEG
IAFJOECGLDPBHMNK
????????????????

b) Solution

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


題意:求解16行16列數獨問題的一組解:給定一個16*16的字母方陣,要求將所有的空格子填上A~P中的一個字符,并滿足以下條件。

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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。