Sudoku

同样是一道dancing links,和poj3074同样是数独问题,只要稍稍改下就能过,我上篇文章里用的是矩阵存储方式,套到这里居然MLE了,只好重新处理,处理过程还是比较麻烦的,终于搞定了,呵呵。这里我给模板化了,能够很容易的处理数独这一类问题

 

代码
1 /*DLX解决sudoku问题,转化为MM * NN的精确覆盖问题*/
2  //解决LL * LL的Sudoku问题
3  #include<stdio.h>
4 #include<math.h>
5 #include<stdlib.h>
6 #include<string.h>
7 #define INF 0x3fffffff
8 #define LL 16
9 #define X 2
10 #define MM (LL * LL * LL)
11 #define NN (LL * LL * 4)
12
13 const int SQ = (int)(sqrt(1.0 * LL));
14 int N, M;
15 int cntc[NN + X];//记录列节点个数
16 int head;
17 int num;
18 char ans[LL + X][LL + X];//存储最后结果
19
20 struct node{
21 int l, r, u, d, x, y, n, c;//c表示当前节点所在列, ans[x][y] = n
22 void set(int _l, int _r, int _u, int _d, int _x, int _y, int _n, int _c){
23 l = _l; r = _r; u = _u; d = _d; x = _x, y = _y, n = _n, c = _c;
24 }
25 }f[MM * 4 + NN + X];
26
27 void Add(int _l, int _x, int _y, int _n, int c){
28 f[++num].x = _x;
29 f[num].y = _y;
30 f[num].n = _n;
31 f[f[num].l = _l].r = num;
32 f[f[num].u = f[c].u].d = num;
33 f[f[num].d = f[num].c = c].u = num;
34 cntc[c]++;
35 }
36 void Addrow(int i, int j, int k){// 如果ans[i][j] = k
37 int t = (i - 1) * LL + j;
38 Add(num + 4, i, j, k, t);
39 Add(num, i, j, k, LL * LL + (i - 1) * LL + k);
40 Add(num, i, j, k, 2 * LL * LL + (j - 1) * LL + k);
41 Add(num, i, j, k, 3 * LL * LL + ((i - 1) / SQ * SQ + (j + SQ - 1) / SQ - 1) * LL + k);
42 }
43 /*删除第c列*/
44 void remove(int c){
45 f[f[c].r].l = f[c].l;
46 f[f[c].l].r = f[c].r;
47
48 int i, j;
49 for (i = f[c].d; i != c; i = f[i].d){
50 for (j = f[i].r; j != i; j = f[j].r){
51 f[f[j].d].u = f[j].u;
52 f[f[j].u].d = f[j].d;
53 cntc[f[j].c]--;
54 }
55 }
56 //printf("remove %d\n", c);
57 }
58 /*恢复第c列*/
59 void resume(int c){
60 f[f[c].r].l = c;
61 f[f[c].l].r = c;
62
63 int i, j;
64 for (i = f[c].d; i != c; i = f[i].d){
65 for (j = f[i].r; j != i; j = f[j].r){
66 f[f[j].d].u = j;
67 f[f[j].u].d = j;
68 cntc[f[j].c]++;
69 }
70 }
71 //printf("resume %d\n", c);
72 }
73 int dfs(){
74 if (f[head].r == head) return 1;
75 int min = INF;
76 int c, i, j;
77 for (i = f[head].r; i != head; i = f[i].r){
78 if (cntc[i] < min){
79 c = i;
80 min = cntc[i];
81 }
82 }
83 remove(c);
84 for (i = f[c].d; i != c; i = f[i].d){
85 ans[f[i].x][f[i].y] = f[i].n;//每选中一行相当于填一小格
86
87 for (j = f[i].r; j != i; j = f[j].r){
88 remove(f[j].c);
89 }
90 if (dfs()) return 1;
91 /*这个顺序很重要,删除和恢复的方向必须相反
92 开始相同,都是向右的,结果TLE了*/
93 for (j = f[i].l; j != i; j = f[j].l){
94 resume(f[j].c);
95 }
96 }
97 resume(c);
98 return 0;
99 }
100
101 int main()
102 {
103 int i, j, k;
104 char s[LL + X][LL + X];
105 int ca = 0;
106 while(scanf("%s", s[0]) != EOF){
107 if(ca) puts("");
108 ca++;
109 for(i = 1; i < LL; i++){
110 scanf("%s", s[i]);
111 }
112 M = MM;
113 N = NN;
114 num = N;
115 for (i = 1; i < N; i++){
116 f[i].set(i - 1, i + 1, i, i, 0, 0, 0, i);
117 }
118 f[0].set(N, 1, 0, 0, 0, 0, 0, 0);
119 f[N].set(N - 1, 0, N, N, 0, 0, 0, N);
120
121 memset(cntc, 0, sizeof(cntc));
122 for (i = 1; i <= LL; i++){
123 for (j = 1; j <= LL; j++){
124 if (s[i - 1][j - 1] == '-'){
125 for (k = 1; k <= LL; k++){
126 Addrow(i, j, k);
127 }
128 }else{
129 k = s[i - 1][j - 1] - 'A' + 1;
130 Addrow(i, j, k);
131 }
132 }
133 }
134 dfs();
135 for(i = 1; i <= LL; i++){
136 for(j = 1; j <= LL; j++) printf("%c", ans[i][j] + 'A' - 1);
137 puts("");
138 }
139 }
140 return 0;
141 }
142

 

posted on 2010-10-06 20:24  ylfdrib  阅读(933)  评论(1编辑  收藏  举报