poj3074 Sudoku 转化为精确覆盖问题 DLX
2010-10-06 10:37
417 查看
Sudoku
终于搞定了,开敲以前,我还在位建图而发愁呢,呵呵
DLX的经典应用:解决数独问题
momodi的论文写的真是不错
建图方式(就是01矩阵)如下
行:
一共9 * 9 * 9 == 729行。一共9 * 9小格,每一格有9种可能性(1 - 9),每一种可能都对应着一行。
列:
一共(9 + 9 + 9) * 9 + 81 == 324 种前面三个9分别代表着9行9列和9小块,乘以9的意思是9种可能(1 - 9),因为每种可能只可以选择一个。81代表着81个小格,限制着每一个小格只放一个数字。
读入数据后,如果为'.',则建9行,即有1-9种可能,否则建一行,表示某小格只能放确定的某个数字。
建完图,加一份模板就可以过了。
代码
终于搞定了,开敲以前,我还在位建图而发愁呢,呵呵
DLX的经典应用:解决数独问题
momodi的论文写的真是不错
建图方式(就是01矩阵)如下
行:
一共9 * 9 * 9 == 729行。一共9 * 9小格,每一格有9种可能性(1 - 9),每一种可能都对应着一行。
列:
一共(9 + 9 + 9) * 9 + 81 == 324 种前面三个9分别代表着9行9列和9小块,乘以9的意思是9种可能(1 - 9),因为每种可能只可以选择一个。81代表着81个小格,限制着每一个小格只放一个数字。
读入数据后,如果为'.',则建9行,即有1-9种可能,否则建一行,表示某小格只能放确定的某个数字。
建完图,加一份模板就可以过了。
代码
/*DLX解决sudoku问题,转化为729*324的精确覆盖问题*/ #include<stdio.h> #include<string.h> #define INF 0x3fffffff #define NN 330 #define MM 740 int N, M; int cntc[NN]; int L[NN * MM], R[NN * MM], U[NN * MM], D[NN * MM], C[NN * MM]; int head; int adj[MM][NN]; int ans[10][10]; /*删除第c列*/ void remove(int c){ L[R[c]] = L[c]; R[L[c]] = R[c]; int i, j; for (i = D[c]; i != c; i = D[i]){ for (j = R[i]; j != i; j = R[j]){ U[D[j]] = U[j]; D[U[j]] = D[j]; cntc[C[j]]--; } } } /*恢复第c列*/ void resume(int c){ L[R[c]] = c; R[L[c]] = c; int i, j; for (i = D[c]; i != c; i = D[i]){ for (j = R[i]; j != i; j = R[j]){ U[D[j]] = j; D[U[j]] = j; cntc[C[j]]++; } } } int dfs(){ if (R[head] == head) return 1; int min = INF; int c, i, j; for (i = R[head]; i != head; i = R[i]){ if (cntc[i] < min){ c = i; min = cntc[i]; } } remove(c); for (i = D[c]; i != c; i = D[i]){ //O[idx++] = (i - 1) / M; int r = (i - 1) / N; int num = (r + 8) / 9; int key = r % 9; if (key == 0) key = 9; int x = (num + 8) / 9; int y = num % 9; if (y == 0) y = 9; ans[x][y] = key; for (j = R[i]; j != i; j = R[j]){ remove(C[j]); } if (dfs()) return 1; /*这个顺序很重要,删除和恢复的方向必须相反 开始相同,都是向右的,结果TLE了*/ for (j = L[i]; j != i; j = L[j]){ resume(C[j]); } } resume(c); return 0; } /*建图*/ int Build(){ int i, j, now, pre, first; head = 0; for (j = head; j < N; j++){ R[j] = j + 1; L[j + 1] = j; } L[head] = j; R[j] = head; /*列双向链表*/ for (j = 1; j <= N; j++){ pre = j; cntc[j] = 0; for (i = 1; i <= M; i++){ if (adj[i][j]){ now = i * N + j; C[now] = j; cntc[j]++; D[pre] = now; U[now] = pre; pre = now; } } now = j; D[pre] = now; U[now] = pre; if (cntc[j] == 0) return 0; } /*行双向链表*/ for (i = 1; i <= M; i++){ pre = first = -1; for (j = 1; j <= N; j++){ if (adj[i][j]){ now = i * N + j; if (pre != -1){ R[pre] = now; L[now] = pre; }else{ first = now; } pre = now; } } if (first != -1){ now = first; R[pre] = now; L[now] = pre; } } return 1; } int main() { char str[85]; int i, j, k; while(scanf("%s", str) != EOF){ if (strcmp(str, "end") == 0) break; memset(adj, 0, sizeof(adj)); for (i = 1; i <= 9; i++){ for (j = 1; j <= 9; j++){ int t = 9 * (i - 1) + j; //for (l = 1; l <= 9; l++){ // adj[9 * (t - 1) + l][t] = 1; if (str[t - 1] == '.'){ for (k = 1; k <= 9; k++){ // adj[t][k] = 1; adj[9 * (t - 1) + k][t] = 1; adj[9 * (t - 1) + k][81 + (i - 1) * 9 + k] = 1; // row adj[9 * (t - 1) + k][162 + (j - 1) * 9 + k] = 1;// col adj[9 * (t - 1) + k][243 + ((i - 1) / 3 * 3 + (j + 2) / 3 - 1) * 9 + k] = 1;// grid } }else{ k = str[t - 1] - '0'; adj[9 * (t - 1) + k][t] = 1; adj[9 * (t - 1) + k][81 + (i - 1) * 9 + k] = 1; // row adj[9 * (t - 1) + k][162 + (j - 1) * 9 + k] = 1;// col adj[9 * (t - 1) + k][243 + ((i - 1) / 3 * 3 + (j + 2) / 3 - 1) * 9 + k] = 1;// grid } // } } } M = 729; N = 324; Build(); dfs(); for(i = 1; i <= 9; i++){ for(j = 1; j <= 9; j++) printf("%d", ans[i][j]); } puts(""); } return 0; }
相关文章推荐
- POJ 3074 Sudoku 转化精确覆盖问题DLX
- POJ 3076 Sudoku 精确覆盖问题DLX
- hdu3111 Sudoku (精确覆盖解数独 DLX)
- POJ 3076 Sudoku DLX精确覆盖
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
- POJ 3074 DLX精确覆盖求解数独问题
- ZOJ 3209 Treasure Map (DLX精确覆盖问题)
- DLX (Dancing Links/舞蹈链)算法——求解精确覆盖问题
- LeetCode----Sudoku Solver+精确覆盖问题解法(Dancing Links)
- DLX(精确覆盖) POJ 3074 Sudoku
- poj3074 DLX精确覆盖
- POJ 3074 Sudoku DLX精确覆盖
- 【POJ3740】Easy Finding DLX(Dancing Links)精确覆盖问题
- HDU 3909 Sudoku(数独转DLX精确覆盖)
- DLX算法求解精确覆盖问题
- DLX模板 +解树独(Dancing Links X)精确覆盖问题
- DLX精确覆盖 poj2676 Sudoku
- (简单) POJ 3074 Sudoku, DLX+精确覆盖。
- DLX精确覆盖解数独问题