POJ 3076 Sudoku (DLX)
2013-11-22 13:04
615 查看
16*16 的数独,DLX的最爱。想了一会儿空着的列要不要删掉,突然发现其实随它搜就好了,只影响深度不影响宽度。或者手动删除一下也没有大碍。
/* Created Time: Thursday, November 21, 2013 PM08:36:56 CST */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 20;
const int MAXC = 4*256+7, MAXNODE = 4*256*16*16+7, MAXR = 16*16+7;
struct DLX {
int S[MAXC]; // 列节点数
int n,sz; // 列数,节点数
int L[MAXNODE],R[MAXNODE],U[MAXNODE],D[MAXNODE]; // 十字链表
int ans[MAXR],ansd; // 解
int row[MAXNODE],col[MAXNODE]; // 对应的行列号
void init(int num) {
n = num;
for (int i = 0; i <= n; i ++) {
U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;
}
L[0] = n; R
= 0;
sz = n+1;
memset(S,0,sizeof(S));
}
void add_raw(int r,vector <int> line) {
int first = sz;
for (int i = 0; i < line.size(); i ++) {
int c = line[i];
L[sz] = sz-1; R[sz] = sz+1; U[sz] = U[c]; D[sz] = 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;
}
#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(i,D,c) FOR(j,R,i) {
U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]] --;
}
}
void restore(int c) {
FOR(i,U,c) FOR(j,L,i) {
U[D[j]] = j; D[U[j]] = j; S[col[j]] ++;
}
L[R[c]] = c;
R[L[c]] = c;
}
bool dfs(int dep) {
if (R[0]==0) {
ansd = dep;
return true;
}
int c = R[0];
FOR(i,R,0)
if (S[i]<S[c]) c = i;
remove(c);
FOR(i,D,c) {
ans[dep] = row[i];
FOR(j,R,i) remove(col[j]);
if (dfs(dep+1)) return true;
FOR(j,L,i) restore(col[j]);
}
restore(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;
char mat
;
int encode(int a,int b,int c) { return (a*16+b)*16+c+1; }
void decode(int v,int &a,int &b,int &c) {
v --;
c = v%16; v /= 16;
b = v%16; v /= 16;
a = v;
}
int get_b(int x,int y) { return x/4*4+y/4; }
const int POS = 0,ROW = 1,COL = 2,BLO = 3;
void get(int x,int y) {
int b = get_b(x,y);
for (int i = 0; i < 16; i ++)
{
if (mat[x][y]!='-' && mat[x][y]!=i+'A') continue;
vector <int> v;
v.push_back(encode(POS,x,y));
v.push_back(encode(ROW,x,i));
v.push_back(encode(COL,y,i));
v.push_back(encode(BLO,b,i));
solver.add_raw(encode(x,y,i),v);
}
}
void work() {
solver.init(4*256);
for (int i = 0; i < 16; i ++) for (int j = 0; j < 16; j ++)
get(i,j);
vector <int> v;
solver.solve(v);
for (int i = 0; i < v.size(); i ++)
{
int a,b,c;
decode(v[i],a,b,c);
mat[a][b] = c+'A';
}
for (int i = 0; i < 16; i ++) puts(mat[i]);
}
int main() {
bool first = true;
while (~scanf("%s",mat[0])) {
for (int i = 1; i < 16; i ++) scanf("%s",mat[i]);
if (first) first = false; else puts("");
work();
}
return 0;
}
/* Created Time: Thursday, November 21, 2013 PM08:36:56 CST */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 20;
const int MAXC = 4*256+7, MAXNODE = 4*256*16*16+7, MAXR = 16*16+7;
struct DLX {
int S[MAXC]; // 列节点数
int n,sz; // 列数,节点数
int L[MAXNODE],R[MAXNODE],U[MAXNODE],D[MAXNODE]; // 十字链表
int ans[MAXR],ansd; // 解
int row[MAXNODE],col[MAXNODE]; // 对应的行列号
void init(int num) {
n = num;
for (int i = 0; i <= n; i ++) {
U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;
}
L[0] = n; R
= 0;
sz = n+1;
memset(S,0,sizeof(S));
}
void add_raw(int r,vector <int> line) {
int first = sz;
for (int i = 0; i < line.size(); i ++) {
int c = line[i];
L[sz] = sz-1; R[sz] = sz+1; U[sz] = U[c]; D[sz] = 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;
}
#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(i,D,c) FOR(j,R,i) {
U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]] --;
}
}
void restore(int c) {
FOR(i,U,c) FOR(j,L,i) {
U[D[j]] = j; D[U[j]] = j; S[col[j]] ++;
}
L[R[c]] = c;
R[L[c]] = c;
}
bool dfs(int dep) {
if (R[0]==0) {
ansd = dep;
return true;
}
int c = R[0];
FOR(i,R,0)
if (S[i]<S[c]) c = i;
remove(c);
FOR(i,D,c) {
ans[dep] = row[i];
FOR(j,R,i) remove(col[j]);
if (dfs(dep+1)) return true;
FOR(j,L,i) restore(col[j]);
}
restore(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;
char mat
;
int encode(int a,int b,int c) { return (a*16+b)*16+c+1; }
void decode(int v,int &a,int &b,int &c) {
v --;
c = v%16; v /= 16;
b = v%16; v /= 16;
a = v;
}
int get_b(int x,int y) { return x/4*4+y/4; }
const int POS = 0,ROW = 1,COL = 2,BLO = 3;
void get(int x,int y) {
int b = get_b(x,y);
for (int i = 0; i < 16; i ++)
{
if (mat[x][y]!='-' && mat[x][y]!=i+'A') continue;
vector <int> v;
v.push_back(encode(POS,x,y));
v.push_back(encode(ROW,x,i));
v.push_back(encode(COL,y,i));
v.push_back(encode(BLO,b,i));
solver.add_raw(encode(x,y,i),v);
}
}
void work() {
solver.init(4*256);
for (int i = 0; i < 16; i ++) for (int j = 0; j < 16; j ++)
get(i,j);
vector <int> v;
solver.solve(v);
for (int i = 0; i < v.size(); i ++)
{
int a,b,c;
decode(v[i],a,b,c);
mat[a][b] = c+'A';
}
for (int i = 0; i < 16; i ++) puts(mat[i]);
}
int main() {
bool first = true;
while (~scanf("%s",mat[0])) {
for (int i = 1; i < 16; i ++) scanf("%s",mat[i]);
if (first) first = false; else puts("");
work();
}
return 0;
}
相关文章推荐
- POJ 3076 Sudoku DLX精确覆盖
- POJ 3076 / ZOJ 3122 Sudoku(DLX)
- POJ 3076 Sudoku (DLX解数独)
- DLX(精确覆盖) 16*16数独 POJ 3076 Sudoku
- (简单) POJ 3076 Sudoku , DLX+精确覆盖。
- 搜索(DLX): POJ 3074 3076 Sudoku
- POJ 3076 Sudoku DLX精确覆盖
- POJ 3076 Sudoku 精确覆盖问题DLX
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- POJ 3076 Sudoku
- poj 2676 Sudoku DLX
- DLX(精确覆盖) POJ 3074 Sudoku
- POJ 3076 Sudoku
- poj 3076 Sudoku //Dancing Links
- poj 3076 Sudoku 数独(16*16)+精确覆盖+DLX 只输出一组解
- poj 3074 Sudoku (精确覆盖,DLX,搜索)
- POJ 3074 Sudoku (DLX解经典数独)
- POJ 3076 Sudoku 笔记
- POJ 3074 Sudoku(DLX+精确覆盖)
- poj 3076(DLX)