const int maxn = 505;
struct Cell
{
int u, d, l, r;
int x, y;
};
Cell cell[maxn*(maxn+6)];
int top;
int cols[maxn], rows[maxn];
int header;void init(int n, int m)
{
top = 0;
header = top++;
memset(cell, 0, sizeof (cell[0]));
for (int i = 0; i < m; ++i)
{
const int me = top++;
int last = cell[header].l; cols[i] = me;
cell[last].r = me, cell[me].l = last;
cell[me].r = header, cell[header].l = me;
cell[me].y = i;cell[me].u = cell[me].d = me;
}
for (int i = 0; i < n; ++i)
{
const int me = top++; rows[i] = me;
int last = cell[header].u;
cell[last].d = me, cell[me].u = last;
cell[me].d = header, cell[header].u = me;
cell[me].x = i;cell[me].l = cell[me].r = me;
}
}void add_element(int x, int y)
{
const int me = top++;
cell[me].x = x, cell[me].y = y;
{
const int row_header = rows[x];
const int last = cell[row_header].l;
cell[last].r = me, cell[me].l = last;
cell[me].r = row_header, cell[row_header].l = me;
}
{
const int col_header = cols[y];
const int last = cell[col_header].u;
cell[last].d = me, cell[me].u = last;
cell[me].d = col_header, cell[col_header].u = me;
}
}
void disable_row(int id, int y)
{
for (int i = cell[rows[id]].r; i != rows[id]; i = cell[i].r)
{
if (cell[i].y != y)
{
cell[cell[i].u].d = cell[i].d;
cell[cell[i].d].u = cell[i].u;
}
}
}
void select_row(int id)
{
int p = rows[id];
for (int q = cell[p].r; q != p; q = cell[q].r)
{
const int col = cols[cell[q].y];
cell[cell[col].l].r = cell[col].r;
cell[cell[col].r].l = cell[col].l;
for (int i = cell[col].d; i != col; i = cell[i].d)
{
disable_row(cell[i].x, cell[q].y);
}
}
}void multi_select_row(int id)
{
int p = rows[id];
for (int q = cell[p].r; q != p; q = cell[q].r)
{
const int col = cols[cell[q].y];
cell[cell[col].l].r = cell[col].r;
cell[cell[col].r].l = cell[col].l;
for (int i = cell[col].d; i != col; i = cell[i].d)
if (i != q)
{
cell[cell[i].l].r = cell[i].r;
cell[cell[i].r].l = cell[i].l;
}
}
}int answers[maxn];
bool exact_cover(int now)
{
int who = cell[header].r;
if (who == header)
{
// 找到一个解
return false; // 需要遍历所有解时返回false,只需要一个解时返回true
}
for (int i = cell[who].d; i != who; i = cell[i].d)
{
select_row(cell[i].x);
answers[now] = cell[i].x;
if (exact_cover(now+1))
{
return true;
}
recover_row(cell[i].x);
}
return false;
}
bool multi_cover(int now)
{
int who = cell[header].r;
if (who == header)
{
// 找到一个解
return false; // 需要遍历所有解时返回false,只需要一个解时返回true
}
for (int i = cell[who].d; i != who; i = cell[i].d)
{
multi_select_row(cell[i].x);
answers[now] = cell[i].x;
if (multi_cover(now+1))
{
return true;
}
multi_recover_row(cell[i].x);
}
return false;
}#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <numeric>
#include <iostream>
using namespace std;
const int maxn = 1005;
struct Cell
{
int u, d, l, r;
int x, y;
};
Cell cell[maxn*(maxn+6)];
int top;
int cols[maxn], rows[maxn];
int header;
int av[maxn];
static inline void init(int n, int m)
{
top = 0;
header = top++;
memset(cell, 0, sizeof (cell[0]));
fill(av, av+m, 0);
for (int i = 0; i < m; ++i)
{
const int me = top++;
int last = cell[header].l; cols[i] = me;
cell[last].r = me, cell[me].l = last;
cell[me].r = header, cell[header].l = me;
cell[me].y = i;cell[me].u = cell[me].d = me;
}
for (int i = 0; i < n; ++i)
{
const int me = top++; rows[i] = me;
int last = cell[header].u;
cell[last].d = me, cell[me].u = last;
cell[me].d = header, cell[header].u = me;
cell[me].x = i;cell[me].l = cell[me].r = me;
}
}
static inline void add_element(int x, int y)
{
const int me = top++;
cell[me].x = x, cell[me].y = y;
{
const int row_header = rows[x];
const int last = cell[row_header].l;
cell[last].r = me, cell[me].l = last;
cell[me].r = row_header, cell[row_header].l = me;
}
{
const int col_header = cols[y];
const int last = cell[col_header].u;
cell[last].d = me, cell[me].u = last;
cell[me].d = col_header, cell[col_header].u = me;
}
++av[y];
}
static inline void disable_row(int id, int y)
{
const int row_header = rows[id];
for (int i = cell[row_header].r; i != row_header; i = cell[i].r)
if (cell[i].y != y)
{
cell[cell[i].u].d = cell[i].d;
cell[cell[i].d].u = cell[i].u;
--av[cell[i].y];
}
}
static inline void enable_row(int id, int y)
{
const int row_header = rows[id];
for (int i = cell[row_header].l; i != row_header; i = cell[i].l)
if (cell[i].y != y)
{
cell[cell[i].u].d = i;
cell[cell[i].d].u = i;
++av[cell[i].y];
}
}
static inline void select_row(int id)
{
const int p = rows[id];
for (int q = cell[p].r; q != p; q = cell[q].r)
{
const int col = cols[cell[q].y];
cell[cell[col].l].r = cell[col].r;
cell[cell[col].r].l = cell[col].l;
--av[cell[q].y];
for (int i = cell[col].d; i != col; i = cell[i].d)
{
disable_row(cell[i].x, cell[q].y);
}
}
}
static inline void recover_row(int id)
{
const int p = rows[id];
for (int q = cell[p].l; q != p; q = cell[q].l)
{
const int col = cols[cell[q].y];
cell[cell[col].l].r = col;
cell[cell[col].r].l = col;
++av[cell[q].y];
for (int i = cell[col].u; i != col; i = cell[i].u)
{
enable_row(cell[i].x, cell[q].y);
}
}
}
int answers[maxn];
int orz;
bool exact_cover(int now)
{
int who = cell[header].r;
if (who == header)
{
orz = now;
return true;
}
int best = 1000000;
for (int i = cell[header].r; i != header; i = cell[i].r)
if (av[cell[i].y] < best)
{
who = i;
best = av[cell[i].y];
if (best <= 1) break;
}
if (best == 0) return false;
for (int i = cell[who].d; i != who; i = cell[i].d)
{
select_row(cell[i].x);
answers[now] = cell[i].x;
if (exact_cover(now+1))
{
return true;
}
recover_row(cell[i].x);
}
return false;
}
// puzzle为输入,其元素是0到9,0表示该位置元素待定
int puzzle[9][9];
void solve()
{
init(81*9, 81*4);
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
for (int val = 0; val < 9; ++val)
if (puzzle[i][j] == 0 || puzzle[i][j] == val + 1)
{
const int id = (i*9+j)*9+val;
const int t = i / 3 * 3 + j / 3;
add_element(id, i*9+j);
add_element(id, 81+i*9+val);
add_element(id, 81+81+j*9+val);
add_element(id, 81+81+81+t*9+val);
}
exact_cover(0);
// 假定exact_cover返回true
for (int i = 0; i < orz; ++i)
{
int id = answers[i] / 9;
int row = id / 9;
int col = id % 9;
int val = answers[i] % 9;
puzzle[row][col] = val+1;
}
}原文:http://blog.csdn.net/baihacker/article/details/38778427