/* 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[n] = 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[N][N];
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)
16*16 的數獨,DLX的最愛。想了一會兒空着的列要不要刪掉,突然發現其實隨它搜就好了,隻影響深度不影響寬度。或者手動刪除一下也沒有大礙。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.