您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: