标签:c++ 算法 链表 dancinglinks
本文简单分析DancingLinks实现中的数据结构设计,给出了精确覆盖问题及其扩展问题的代码,并应用于数独问题。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; } }
标签:c++ 算法 链表 dancinglinks
原文地址:http://blog.csdn.net/baihacker/article/details/38778427