POJ 3074 3076 Sudoku(Dancing Links)
2013-03-21 23:15
357 查看
题意:
求解数独。
思路:
1. 如何用 dancing links 求解数独?其中的精确覆盖策略十分精妙,感叹之余只能膜拜 Knuth 了;
2. 如何把数独问题分解成矩阵,假设是 9*9 数独问题,则分下面 4 种限制条件:
a) 每一行元素不能重复;
b) 每一列元素不能重复;
c) 每个 3*3 矩阵元素不能重复;
d) 每个格子只能存放一个数字;
3. 达到上述 4 个条件之后就可以构造 01 方阵了,列表示对于元素的限制,行代表所有格子的选择。所以有 81 * 4 列(对应上面 4 个条件),有 81 * 9 行。
5. 求解的要求是:选定其中的行,当且仅当把所有的列选择完毕之后,停止递归,当然要求每一列只有一个 1 存在。此时 Q 里面存放的就是一个可行解。
6. 其中 S 数组里面存放的是每一列 1 的个数。按照 DLX 算法的要求,每次递归总选择 1 最少的列开始,这样能够有效的减少分支。因为最终只是寻找一个可行解就返回。
7. Dancing Links 在下面 CSDN 链接的几篇博客比较清楚。简单描述下:
a) 选定 1 最少的列,对其进行删除,同时删除此列上存在 1 的行。因为某个列只能选择一个 1 的缘故,所以选择了此列上某个 1 便不能选择其它 1;
b) 选定删除列的某一行,删除此行上面存在 1 的列,即某一行达到了列所在的几个限制条件,理应对列进行删除。删除列时的操作同 a) 的操作;
c) 如果所有的列都被删除了,则我们的任务完成,Q 中保存的即是我们曾经选中的行,即可行解。否则重复 a) 的操作或者进行回溯操作;
http://www.cppblog.com/notonlysuccess/archive/2009/07/10/89701.aspx
http://blog.csdn.net/mu399/article/details/7627763
// 3074
求解数独。
思路:
1. 如何用 dancing links 求解数独?其中的精确覆盖策略十分精妙,感叹之余只能膜拜 Knuth 了;
2. 如何把数独问题分解成矩阵,假设是 9*9 数独问题,则分下面 4 种限制条件:
a) 每一行元素不能重复;
b) 每一列元素不能重复;
c) 每个 3*3 矩阵元素不能重复;
d) 每个格子只能存放一个数字;
3. 达到上述 4 个条件之后就可以构造 01 方阵了,列表示对于元素的限制,行代表所有格子的选择。所以有 81 * 4 列(对应上面 4 个条件),有 81 * 9 行。
5. 求解的要求是:选定其中的行,当且仅当把所有的列选择完毕之后,停止递归,当然要求每一列只有一个 1 存在。此时 Q 里面存放的就是一个可行解。
6. 其中 S 数组里面存放的是每一列 1 的个数。按照 DLX 算法的要求,每次递归总选择 1 最少的列开始,这样能够有效的减少分支。因为最终只是寻找一个可行解就返回。
7. Dancing Links 在下面 CSDN 链接的几篇博客比较清楚。简单描述下:
a) 选定 1 最少的列,对其进行删除,同时删除此列上存在 1 的行。因为某个列只能选择一个 1 的缘故,所以选择了此列上某个 1 便不能选择其它 1;
b) 选定删除列的某一行,删除此行上面存在 1 的列,即某一行达到了列所在的几个限制条件,理应对列进行删除。删除列时的操作同 a) 的操作;
c) 如果所有的列都被删除了,则我们的任务完成,Q 中保存的即是我们曾经选中的行,即可行解。否则重复 a) 的操作或者进行回溯操作;
http://www.cppblog.com/notonlysuccess/archive/2009/07/10/89701.aspx
http://blog.csdn.net/mu399/article/details/7627763
// 3074
#include <iostream> #include <algorithm> using namespace std; const int INFS = 0x3fffffff; const int MAXC = 81 * 4; const int MAXR = 81 * 9; const int MAXN = MAXC * MAXR + 10; int U[MAXN], D[MAXN], L[MAXN], R[MAXN]; int grid[MAXR+10][MAXC+10], col[MAXN], row[MAXN], S[MAXC+10], Q[MAXR+10], QC; void remove(int c) { L[R[c]] = L[c]; R[L[c]] = R[c]; for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]] -= 1; } } } void resume(int c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { U[D[j]] = D[U[j]] = j; S[col[j]] += 1; } } R[L[c]] = L[R[c]] = c; } bool dfs() { if (R[0] == 0) return true; int mins = INFS, c = 0; for (int i = R[0]; i != 0; i = R[i]) { if (S[i] < mins) mins = S[i], c = i; } remove(c); for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) remove(col[j]); Q[QC++] = row[i]; if (dfs()) return true; QC -= 1; for (int j = L[i]; j != i; j = L[j]) resume(col[j]); } resume(c); return false; } void solve(int ans[]) { QC = 0; dfs(); for (int i = 0; i < QC; i++) ans[(Q[i]-1)/9] = (Q[i] - 1) % 9 + 1; } void buildmatrix(char data[]) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (data[i*9+j] == '.') { for (int k = 1; k <= 9; k++) { int r = (i * 9 + j) * 9 + k; int c1 = 81 * 0 + i * 9 + k; int c2 = 81 * 1 + j * 9 + k; int c3 = 81 * 2 + (i / 3 * 3 + j / 3) * 9 + k; int c4 = 81 * 3 + i * 9 + j + 1; grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1; } } else { int k = data[i*9+j] - '0'; int r = (i * 9 + j) * 9 + k; int c1 = 81 * 0 + i * 9 + k; int c2 = 81 * 1 + j * 9 + k; int c3 = 81 * 2 + (i / 3 * 3 + j / 3) * 9 + k; int c4 = 81 * 3 + i * 9 + j + 1; grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1; } } } } void builddlx() { memset(S, 0, sizeof(S)); for (int i = 1; i <= MAXC; i++) R[i-1] = L[i+1] = U[i] = D[i] = i; R[MAXC] = L[1] = 0; int c = MAXC; for (int i = 1; i <= MAXR; i++) { int cflag = -1; for (int j = 1; j <= MAXC; j++) { if (grid[i][j] == 1) { c += 1; S[j] += 1; row[c] = i; col[c] = j; U[c] = U[j]; D[c] = j; D[U[j]] = c; U[j] = c; if (cflag == -1) { R[c] = L[c] = c; cflag = c; } else { L[c] = L[cflag]; R[c] = cflag; R[L[c]] = c; L[cflag] = c; } } } } } bool initdata() { char data[100]; scanf("%s", data); if (data[0] == 'e') return false; memset(grid, 0, sizeof(grid)); buildmatrix(data); builddlx(); return true; } int main() { while (initdata()) { int ans[100]; solve(ans); for (int i = 0; i < 81; i++) printf("%d", ans[i]); printf("\n"); } return 0; } // 3076
#include <iostream> #include <algorithm> using namespace std; const int INFS = 0x3fffffff; const int MAXC = 16 * 16 * 4; const int MAXR = 16 * 16 * 16; const int MAXN = MAXC * MAXR + 10; int U[MAXN], D[MAXN], L[MAXN], R[MAXN]; int grid[MAXR+10][MAXC+10], col[MAXN], row[MAXN], S[MAXC+10], Q[MAXR+10], QC; char data[20][20]; void remove(int c) { L[R[c]] = L[c]; R[L[c]] = R[c]; for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]] -= 1; } } } void resume(int c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { U[D[j]] = D[U[j]] = j; S[col[j]] += 1; } } R[L[c]] = L[R[c]] = c; } bool dfs() { if (R[0] == 0) return true; int mins = INFS, c = 0; for (int i = R[0]; i != 0; i = R[i]) { if (S[i] < mins) mins = S[i], c = i; } remove(c); for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) remove(col[j]); Q[QC++] = row[i]; if (dfs()) return true; QC -= 1; for (int j = L[i]; j != i; j = L[j]) resume(col[j]); } resume(c); return false; } void solve(char ans[]) { QC = 0; dfs(); for (int i = 0; i < QC; i++) ans[(Q[i]-1)/16] = (Q[i] - 1) % 16 + 'A'; } void buildmatrix() { for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { if (data[i][j] == '-') { for (int k = 1; k <= 16; k++) { int r = (i * 16 + j) * 16 + k; int c1 = 256 * 0 + i * 16 + k; int c2 = 256 * 1 + j * 16 + k; int c3 = 256 * 2 + (i / 4 * 4 + j / 4) * 16 + k; int c4 = 256 * 3 + i * 16 + j + 1; grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1; } } else { int k = data[i][j] - 'A' + 1; int r = (i * 16 + j) * 16 + k; int c1 = 256 * 0 + i * 16 + k; int c2 = 256 * 1 + j * 16 + k; int c3 = 256 * 2 + (i / 4 * 4 + j / 4) * 16 + k; int c4 = 256 * 3 + i * 16 + j + 1; grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1; } } } } void builddlx() { memset(S, 0, sizeof(S)); for (int i = 1; i <= MAXC; i++) R[i-1] = L[i+1] = U[i] = D[i] = i; R[MAXC] = L[1] = 0; int c = MAXC; for (int i = 1; i <= MAXR; i++) { int cflag = -1; for (int j = 1; j <= MAXC; j++) { if (grid[i][j] == 1) { c += 1; S[j] += 1; row[c] = i; col[c] = j; U[c] = U[j]; D[c] = j; D[U[j]] = c; U[j] = c; if (cflag == -1) { R[c] = L[c] = c; cflag = c; } else { L[c] = L[cflag]; R[c] = cflag; R[L[c]] = c; L[cflag] = c; } } } } } bool initdata() { while (scanf("%s", data[0]) != EOF) { for (int i = 1; i < 16; i++) scanf("%s", data[i]); memset(grid, 0, sizeof(grid)); buildmatrix(); builddlx(); return true ; } return false; } int main() { while (initdata()) { char ans[300]; solve(ans); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { printf("%c", ans[i*16+j]); } printf("\n"); } printf("\n"); } return 0; } 3239 1077
相关文章推荐
- POJ 3074 Sudoku(数独|Dancing Links精确覆盖)
- POJ 3074 Sudoku (Dancing Links)
- poj 3076 Sudoku(Dancing Links)
- dancing links 算法学习小记 Poj 3074 Sudoku (数独)
- POJ 3076 Sudoku (dancing links)
- poj 3074/3076 数独(Dancing Links)
- POJ 3076 Sudoku (dancing links)
- 搜索(DLX): POJ 3074 3076 Sudoku
- poj 3074 Sudoku(Dancing Links)
- POJ 2676 Sudoku (搜索,Dancing Links)
- (模板题)poj 3074 Sudoku(DLX算法)
- POJ 3074 Sudoku【DancingLinks,数独】
- POJ 3076 / ZOJ 3122 Sudoku(DLX)
- POJ 3074,3076,2676 数独 Dancing Links舞蹈链
- pku 3074 3076 Sudoku 问题
- poj 3704 Sudoku(Dancing Links)
- POJ 3076 Sudoku 笔记
- POJ 3076 Sudoku 数独模板
- POJ 2676 3074 3076 数独3题 Dancing Links
- POJ 3074 Sudoku DLX精确覆盖