Sudoku (数独)和精确覆盖
来源:互联网 发布:意大利淘宝 编辑:程序博客网 时间:2024/04/29 14:01
偶然看到《谈谈 Sudoku (数独)》[1]的博文,心血来潮把文章的算法实现了一番。有关Sudoku的具体介绍可参考维基百科。
具体解法有:回溯、精确匹配。回溯解法《谈谈 Sudoku (数独)》有比较详细的阐述,所以本文只记录一下精确覆盖的解法。
精确覆盖[2]
数度到矩阵的转换
Algorithm X使用了矩阵的表示方法,因此在需要把数度表示成矩阵的形式。具体转换如下:假设一个给定的9 * 9数度中,有N个空格需要求解,那么矩阵M的行数R=N * 9,列数C=4 * N。其中:
a.M[i][j]=1, 0<=j<N,表示第j个空格考虑行、列、块以后可以取数字i%9 + 1
b.M[i][j]=1, N<=j<2N,表示第j个空格只考虑行的情况下可以取数字i%9 + 1
c.M[i][j]=1, 2N<=j<3N,表示第j个空格只考虑列的情况下可以取数字i%9 + 1
1.http://blog.csdn.net/Solstice/article/details/2096209
2.http://en.wikipedia.org/wiki/Exact_cover
3.http://en.wikipedia.org/wiki/Knuth%27s_Algorithm_X
4.http://lanl.arxiv.org/PS_cache/cs/pdf/0011/0011047v1.pdf
具体解法有:回溯、精确匹配。回溯解法《谈谈 Sudoku (数独)》有比较详细的阐述,所以本文只记录一下精确覆盖的解法。
精确覆盖[2]
- 1.精确覆盖 给定集合X、S、T。S是X的子集的集合,T是S的子集,如果X中每个元素都只被T中的一个元素包含,那么T就是X的精确覆盖
- 2.精确命中(exact hitting) 给定集合X、S、Y。S是X的子集的集合,Y是X的子集,如果Y中每个元素都只被S中的一个元素包含,那么Y就是S的精确命中
- 3.表示方法 列表、矩阵
- 4.实现 Knuth's Algorithm X[3],解决精确覆盖的深度优先、递归、不确定算法。
大概思想与技巧[4]:利用矩阵的表示方法,同时把行列表示成双向环列表(Dancing Link),在删除列表中的元素时,只更新前后(上下)的相关指针值。
数度到矩阵的转换
Algorithm X使用了矩阵的表示方法,因此在需要把数度表示成矩阵的形式。具体转换如下:假设一个给定的9 * 9数度中,有N个空格需要求解,那么矩阵M的行数R=N * 9,列数C=4 * N。其中:
a.M[i][j]=1, 0<=j<N,表示第j个空格考虑行、列、块以后可以取数字i%9 + 1
b.M[i][j]=1, N<=j<2N,表示第j个空格只考虑行的情况下可以取数字i%9 + 1
c.M[i][j]=1, 2N<=j<3N,表示第j个空格只考虑列的情况下可以取数字i%9 + 1
d.M[i][j]=1, 3N<=j<4N,表示第j个空格只考虑块的情况下可以取数字i%9 + 1
代码如下:
#include <stdlib.h>#include <stdio.h>struct column_object;typedef struct data_obj_ { struct data_obj_ *l, *r, *u, *d; struct column_object *c; int real_r;} data_object;typedef data_object list_header;struct column_object { data_object* data; int s; int n;};static inline voidappend_right_tail(data_object *tail, data_object *p2);static inline voidappend_down_tail(data_object *tail, data_object *p2);static void inlineinit_data_obj(data_object *p);static void inlineinit_column_obj(struct column_object *c);static inline voidfree_resource(struct column_object *h);static data_object *create_dlx(int *matrix, int r, int c, struct column_object **h);static intsearch_dlx(struct column_object *h, int c, int k, data_object **out, int **r_out, int *r_cnt_out);static inline voidcover_column(data_object *c);static inline voiduncover_column(data_object *c);static data_object *create_dlx(int *matrix, int r, int c, struct column_object **h){ int i, j, ele_cnt; data_object *data, *right_most, *cur, *tail; struct column_object *root; for (i = 0, ele_cnt = 0; i < r; ++i) for (j = 0; j < c; ele_cnt += matrix[i * c + j], ++j) ; data = (list_header *) malloc(sizeof(data_object) * (ele_cnt + 1 + c)); root = (struct column_object *) malloc(sizeof (struct column_object) * (c + 1)); *h = root; root->data = data++; init_column_obj(root); root->s = r + 1; for (i = 0, ++root; i < c; ++i, ++root) { cur = root->data = data++; init_column_obj(root);root->n = i; append_right_tail((root - 1)->data, root->data); } for (i = 0; i < r; ++i) { right_most = NULL; for (j = 0; j < c; ++j) { if (matrix[i * c + j] == 0) continue; cur = data++; cur->real_r = i; if (right_most != NULL) { append_right_tail(right_most, cur); } else { init_data_obj(cur); right_most = cur; } tail = (*h + j + 1)->data->u; append_down_tail(tail, cur); } } return (*h)->data + c + 1;}static inline voidfree_resource(struct column_object *h){ free(h->data); free(h);}intsearch(int *matrix, int r, int c, int **r_out, int *r_cnt_out){ struct column_object *h; create_dlx(matrix, r, c, &h); data_object **out = (data_object **) malloc(sizeof (data_object *) * r); int ans = search_dlx(h, c, 0, out, r_out, r_cnt_out); free_resource(h); free(out); return ans;}static intsearch_dlx(struct column_object *h, int c, int k, data_object **out, int **r_out, int *r_cnt_out){ int c_it; data_object *id_it, *sel_d, *jd_it; if (h->data->r == h->data) { for (c_it = 0; c_it < k; ++c_it) (*r_out)[c_it] = out[c_it]->real_r; *r_cnt_out = c_it; return 0; } for (sel_d = h->data->d, id_it = sel_d->r; id_it != sel_d; id_it = id_it->r) if (sel_d->c->s > id_it->c->s) sel_d = id_it; /*conver column sel_d*/ cover_column(sel_d); for (id_it = sel_d->d; id_it != sel_d; id_it = id_it->d) { out[k] = id_it; for (jd_it = id_it->r; jd_it != id_it; jd_it = jd_it->r) cover_column(jd_it->c->data); if (search_dlx(h, c, k + 1, out, r_out, r_cnt_out) == 0) return 0; for (jd_it = id_it->l; jd_it != id_it; jd_it = jd_it->l) uncover_column(jd_it->c->data); } uncover_column(sel_d); return -1;}static inline voidcover_column(data_object *c){ data_object *i, *j; c->r->l = c->l; c->l->r = c->r; for (i = c->d; i != c; i = i->d) { for (j = i->r; j != i; j = j->r) {j->d->u = j->u; j->u->d = j->d;j->c->s -= 1; } }}static inline voiduncover_column(data_object *c){ data_object *i, *j; for (i = c->u; i != c; i = i->u) { for (j = i->l; j != i; j = j->l) {j->c->s += 1;j->d->u = j; j->u->d = j; } }c->r->l = c; c->l->r = c;}static inline voidappend_right_tail(data_object *tail, data_object *p2){p2->l = tail;p2->r = tail->r;tail->r->l = p2;tail->r = p2;}static inline voidappend_down_tail(data_object *tail, data_object *p2){p2->c = tail->c;p2->u = tail;p2->d = tail->d;tail->d->u = p2;tail->d = p2;p2->c->s += 1;}static void inlineinit_data_obj(data_object *p){p->l = p->r = p->d = p->u = p;}static void inlineinit_column_obj(struct column_object *c){data_object *p = c->data;init_data_obj(p);p->c = c;c->s = 0;}
1.http://blog.csdn.net/Solstice/article/details/2096209
2.http://en.wikipedia.org/wiki/Exact_cover
3.http://en.wikipedia.org/wiki/Knuth%27s_Algorithm_X
4.http://lanl.arxiv.org/PS_cache/cs/pdf/0011/0011047v1.pdf
- Sudoku (数独)和精确覆盖
- 【POJ】2676 Sudoku 【数独】精确覆盖
- 【UVALive】2659 Sudoku 【数独】精确覆盖
- 【HDU】2780 Su-Su-Sudoku【数独】精确覆盖
- POJ 3074 Sudoku(数独|Dancing Links精确覆盖)
- DLX(精确覆盖) 16*16数独 POJ 3076 Sudoku
- poj 3074(数独 Dancing Link精确覆盖)
- zoj 3122(数独 Dancing Links精确覆盖)
- POJ 3074 DLX精确覆盖求解数独问题
- 谈谈数独(Sudoku)
- 数独(sudoku)实现
- PKU2676 Sudoku 数独
- poj2676 Sudoku 数独
- 数独(sudoku)C++
- POJ2676 Sudoku [数独]
- poj2676 Sudoku 数独
- Sudoku 数独
- 数独Sudoku
- 带参数的日期转化
- H3流程设计器及Sharepoint2007集成
- 浅谈javascript函数劫持
- C#实现 ORACLE的分页功能
- DISCUZ 附件批量上传列表空白等问题原因分析及解决思路
- Sudoku (数独)和精确覆盖
- 《女孩梦三十》
- 中国报恩网负债运转5年濒临关闭 又获资助
- pidgin2.9在ubuntu10.04的安装 & vmware
- test
- ARM与射频芯片TRF796x的SPI通信研究
- Linux Shell 之 sed (追加文本)
- signal函数、sigaction函数及信号集操作函数
- 二叉树遍历