LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
来源:互联网 发布:软件系统工程师学费 编辑:程序博客网 时间:2024/05/08 23:23
题目链接: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.
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;}
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- POJ 3076 Sudoku DLX精确覆盖
- POJ 3076 Sudoku 精确覆盖问题DLX
- POJ 3074 Sudoku(DLX+精确覆盖)
- poj 3074 Sudoku (精确覆盖,DLX,搜索)
- DLX(精确覆盖) POJ 3074 Sudoku
- POJ 3074 Sudoku DLX精确覆盖
- DLX(精确覆盖) 16*16数独 POJ 3076 Sudoku
- DLX精确覆盖 poj2676 Sudoku
- POJ 3074 Sudoku 转化精确覆盖问题DLX
- poj 3740 DLX(精确覆盖)
- HDU 3909 Sudoku(数独转DLX精确覆盖)
- HDU 4069 Squiggly Sudoku DLX 精确覆盖
- DLX精确覆盖 hdu4069 Squiggly Sudoku
- zoj - 3209 - Treasure Map(精确覆盖DLX)
- ZOJ 3209 Treasure Map(DLX精确覆盖)
- ZOJ 3209 Treasure Map (DLX精确覆盖)
- ZOJ 3290 Treasure Map(DLX+精确覆盖)
- sublime license
- Oracle PeopleSoft Feed Publishing Framework
- Codeforces Round #277 (Div. 2) D 计数问题,划分等价类
- C++primer(第五版)第四章表达式学习笔记(含习题c++源代码和C++11特性)
- image blur
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- 3D重构基础七--structure and motion
- Red Hat下 关于apache 的操作权限
- 创建链表指针问题
- C语言第三回合:数据类们的PK
- 基本arm210开发板智能家居项目展示
- 数据结构 第五章 树和二叉树
- js获取当前时间戳
- 图片不存在时,显示一个默认的图片