Knuth对
算法
的描述就是一种享受~
从算法解决什么问题
(Exact Cover
)(精确覆盖),到算法的实现(DancingLink
),相当的自然,而且对算法的描述,非常自然,很想得通~赞赞!
看完就知道,关键是如何实现一个那样的矩阵表示,想想C语言的矩阵表示,如果拷贝实在太费时,怎么办呢?dancing Links , 用链表实现~赞~
Knuth's Algorithm X
Donald Knuth
's Algorithm X
is a recursive
, nondeterministic
, depth-first
, backtracking
algorithm
that finds all solutions to the exact cover
problem represented by a matrix A
consisting of 0s and 1s. The goal is to select a subset of the rows so that the digit 1 appears in each column exactly once.
-
If the matrix A
is empty, the problem is solved; terminate successfully.
-
Otherwise choose a column
c
(
deterministically
). 这里是确定性的,找到含有1最少的那个column
-
原因是:If column c is entirely zero, there are no subalgorithms and the process terminates unsuccessfully -所以找到含有1最少的那个column,可以尽快结束算法。
-
Golomb and Baumert [16] suggested choosing a subproblem that leads to the fewest branches
-
这是启发式
-
Choose a row r
such that A
r
, c
= 1 (nondeterministically
).
-
Include row r
in the partial solution.
-
For each column j
such that A
r
, j
= 1,for each row i
such that A
i
, j
= 1,delete row i
from matrix A
;delete column j
from matrix A
.
-
Repeat this algorithm recursively on the reduced matrix A
.
-from wikipedia
这个图很经典~
/**
* pku 3740 -dancing link
* 完全按照knuth论文的语意实现。
* 算法很复杂,但是初始化数据结构更复杂。。
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ROW 20
#define COL 305
#define INF 9999999
// 必须是按照与删除顺序相反的顺序恢复,才对
int rr, cc;
//both used for data node obj & column obj
struct NODE {
int L, R, U, D;
int C; //points to the column object
int S; //column_header use
char N;//column_header use
};
struct NODE nodes[ROW * (COL + 1)]; //nodes[0...cc]作为column_header //nodes[999作为header] nodes[1000 - ...]存放node
int head_id = 999;//没被占用
struct NODE &head = nodes[head_id];//用nodes[-1]表示
int nodes_id;
int choose_column() {
int s = INF;
int c = head.R;
for (int j = head.R; j != head_id; j = nodes[j].R)
if (nodes[j].S < s) {
c = j;
s = nodes[j].S;
}
return c;
}
void cover(int c) {
// printf("cover(%d)", c);
nodes[nodes[c].R].L = nodes[c].L;
nodes[nodes[c].L].R = nodes[c].R;
for (int r = nodes[c].D; r != c; r = nodes[r].D) {
// printf("r:%d\n", r);
for (int j = nodes[r].R; j != r; j = nodes[j].R) {
// printf("j:%d\t", j);//here
nodes[nodes[j].D].U = nodes[j].U;
nodes[nodes[j].U].D = nodes[j].D;
nodes[nodes[j].C].S--;
}
}
}
void uncover(int c) {
for (int i = nodes[c].U; i != c; i = nodes[i].U)
for (int j = nodes[i].L; j != i; j = nodes[j].L) {
nodes[nodes[j].C].S++;
nodes[nodes[j].U].D = j;
nodes[nodes[j].D].U = j;
}
nodes[nodes[c].L].R = c;
nodes[nodes[c].R].L = c;
}
int search(int k) {
// printf("search(%d)\n", k);
if (head.R == head_id)
return 1;
int c = choose_column();
// printf("choose_colume return: %d\n", c);
cover(c);
for (int r = nodes[c].D; r != c; r = nodes[r].D) {
// printf("r:%d\n", r);
for (int j = nodes[r].R; j != r; j = nodes[j].R) {
// printf("j:%d\t", j);
cover(nodes[j].C);
}
if (search(k + 1))
return 1;//modified
for (int j = nodes[r].L; j != r; j = nodes[j].L) {
uncover(nodes[j].C);
}
}
uncover(c);
return 0;
}
int mat[ROW][COL];
int map[ROW][COL];
void link_row(int r) {
// printf("link_row(%d)",r);
int c1 = 0;
for (c1 = 0; c1 < cc; c1++)
if (mat[r][c1])
break;
if (c1 == cc)
return;
int id1 = map[r][c1];
nodes[id1].L = nodes[id1].R = id1;// init link list
for (int c = 0; c < cc; c++)
if (mat[r][c] && c != c1) {
int id2 = map[r][c];
nodes[id2].R = nodes[id1].R;
nodes[id2].L = id1;
nodes[nodes[id1].R].L = id2;
nodes[id1].R = id2;
}
}
void link_col(int c) {
// printf("link_col(%d)",c);
//init nodes[c]
nodes[c].U=nodes[c].D = nodes[c].C =c;
nodes[c].S =0;
//insert column_header
nodes[c].R = head.R;
nodes[c].L = head_id;
nodes[head.R].L = c;
head.R = c;
int id = -1;
//set column nodes
for (int r = 0; r < rr; r++) {
if (!mat[r][c])
continue;
id = map[r][c];
nodes[id].C = c;
nodes[c].S++; //update Sum
//insert node
nodes[id].D = nodes[c].D;
nodes[id].U = c;
nodes[nodes[c].D].U = id;
nodes[c].D = id;
}
}
void init() {
memset(nodes, 0, sizeof(nodes));
head.L = head.R = head_id;
nodes_id = head_id + 1;
for (int r = 0; r < rr; r++)
for (int c = 0; c < cc; c++)
if (mat[r][c] == 1)
map[r][c] = nodes_id++;
for (int r = 0; r < rr; r++) {
link_row(r);
}
for (int c = 0; c < cc; c++) {
link_col(c);
}
}
int main() {
while (EOF != scanf("%d%d", &rr, &cc)) {
for (int r = 0; r < rr; r++)
for (int c = 0; c < cc; c++) {
scanf("%d", &mat[r][c]);
}
fflush(stdout);
init();
if (search(0))
printf("Yes, I found it\n");
else
printf("It is impossible\n");
}
return 0;
}
/*
1 1
1
1 2
1 1
1 2
0 0
1 2
0 1
*/
/**
3 3
0 1 0
0 0 1
1 0 0
4 4
0 0 0 1
1 0 0 0
1 1 0 1
0 1 0 0
4 6
0 0 0 1 1 1
1 0 0 0 0 0
1 1 0 1 0 0
0 0 1 0 0 0
4 6
0 0 0 1 1 1
1 0 0 0 0 0
1 1 0 1 0 0
0 1 1 0 0 0
*/
/**
yes
no
no
yes
**/
Knuth这个复杂度分析,太精细了~
Each update involves about 14 memory accesses when the S heuristic is used, and about
8 accesses when S is ignored. Thus the S heuristic multiplies the total number of memory
accesses by a factor of approximately (14 × 3,617,723)/(8 × 17,818,752) 36%
实现:
注意: cover和uncover一定要完全反序~(Notice that uncovering takes place in precisely the reverse order of the covering operation)
实现过程中,
最好不要使用这样的数据结构,
struct
point
{
int
L;
int
R;
int
U;
int
D;
int
Sum;
int
x, y;
}
p[
1010
*
1010
];
因为需要写:
nodes[nodes[c].R].L = nodes[c].L;
nodes[nodes[c].L].R = nodes[c].R;
来表示删除,而Knuth使用
L[R[c]]=L[c]
R[L[c]]=R[c].表示删除
而不要用真正的指针
,因为那样很难调试。。
分享到:
相关推荐
### ACM Dancing Link 数据结构详解 #### 一、概述 **ACM Dancing Link**(简称 DLX)是一种高效解决**精确覆盖问题**的数据结构。它在实际应用中特别适用于解决诸如**数独**这类问题,其核心思想是通过双向链表...
标题中的"DancingLink acm 算法 跳表"是三种不同的数据结构或算法技术,它们在解决特定问题时都有其独特的作用。这里分别介绍这三个概念: 1. **DancingLink算法**:Dancing Links(舞动链接)是由Donald Knuth提出...
解数独问题属于计算机科学中的算法问题,而dancing links是一种用于优化算法效率的技术。Donald E. Knuth 是一位著名的计算机科学家,他提出的dancing links方法在实现算法,尤其是解决类似于数独这样的约束满足问题...
标题所蕴含的知识点是"Dancing Links 解决骑士遍历问题"。"Dancing Links"是指X算法的一种实现方式,即通过链表的数据结构解决精确覆盖问题。在此问题中,骑士遍历问题即马踏棋盘问题,是该算法的一个应用场景。该...
浙江省第6届 ACM大学生程序设计竞赛解题报告 本文是 浙江省第6届 ACM大学生程序设计竞赛的解题报告,由曹鹏所著。该报告涵盖了竞赛中的11道题目,涵盖了... Treasure Map:该题是最难的题目,需要使用 dancing link。
#### 4.7 Dancing Link 用于解决精确覆盖问题。 ### 五、计算几何 计算几何部分涉及了众多几何对象的定义、性质和算法: #### 5.1 各种公式 包括计算距离、角度等。 #### 5.2 基本类型定义 定义了几何对象的基本...
Calculate all Sudoku answers using brute dfs, you can develop this code using dancing link to catch a high speed. Pay attention to that this code may run a long time and I haven't added any sentences ...
在下曾学习于 AC自动机详细讲解 必备技能: trie + KMP 文章目录1. 结构体2. 添加模式串3. 求失配指针4. 匹配文本串ends:模板1 统计出现的模式串个数ends:模板2 统计出现次数最多的模式串(带初始化)ends:模板3 ...
标题与描述中的“Dancing Links”(舞动链接)是一种数据结构操作技术,由计算机科学领域的传奇人物Donald E. Knuth在2000年提出。该技术特别适用于解决回溯算法中的问题,如N皇后问题等。Knuth在文章中强调了这种...
本话题主要探讨的是"智慧拼珠求解"与"智慧金字塔求解"这两种问题,以及它们对应的解决方案——回溯法和Dancing Links算法。下面将详细阐述这两个概念及其应用。 首先,让我们了解"智慧珠"。智慧珠是一种典型的组合...
- 数据结构:Dancing Links 是一种基于链表的特殊数据结构,其中每个元素都有四个链接,分别指向相邻的元素和相对元素。 - 压缩表示:拼图的状态可以压缩为一个二维数组,表示各个位置的块是否已放置。 - 搜索...
: PIU 模拟器 :woman_dancing: :down-left_arrow: :down-right_arrow: :white_large_square: :up-left_arrow: :up-right_arrow: :man_dancing: :多人游戏库 :video_game: :link: :video_game:大湾区果酱 2021 所有...
"Dancing Dissolve"则是动态溶解,增加了过渡的动态效果,使画面更富有趣味性。"Darken"表示变暗,"Multiply"代表正片叠底,这种混合模式可以使底层颜色变暗,常用于实现图像的叠加效果。"Color Burn"是颜色加深,...
这个指令使得我们可以轻松地...<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css"> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> ...
Dancing tree 297 2-3 tree 298 2-3-4 tree 299 Queaps 301 Fusion tree 305 Bx-tree 309 Heaps 312 Heap 312 Binary heap 315 Binomial heap 321 Fibonacci heap 326 2-3 heap 331 Pairing heap 331 Beap 334 ...
3. 主 + 系 + 表 (S+Link.V+C):如 "They are heroes." 这里"are"是系动词,"heroes"是表语,描述主语的特性。 4. 主 + 谓 + 双宾 (S+Vt+InO+DO):如 "I offered him 5 dollars." 这里有直接宾语"him"和间接宾语"5 ...
然后,你可以通过`avfilter_link`函数连接输入和输出过滤器,使得视频流能够通过过滤器链路。 3. **初始化和配置上下文**:在开始处理视频之前,需要初始化`AVCodecContext`并设置合适的编解码器参数。这包括设置...