`
idning
  • 浏览: 138505 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

dancing link

阅读更多

Knuth对 算法 的描述就是一种享受~
    从算法解决什么问题Exact Cover )(精确覆盖),到算法的实现(DancingLink ),相当的自然,而且对算法的描述,非常自然,很想得通~赞赞!

  看完就知道,关键是如何实现一个那样的矩阵表示,想想C语言的矩阵表示,如果拷贝实在太费时,怎么办呢?dancing Links , 用链表实现~赞~

 

 

Knuth's Algorithm X

Donald Knuth 's Algorithm X  is a recursivenondeterministicdepth-firstbacktracking  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.


  1. If the matrix A  is empty, the problem is solved; terminate successfully.
  2. Otherwise choose a column  c  ( deterministically ). 这里是确定性的,找到含有1最少的那个column  why -Lin Yang 3/30/10 11:07 AM  
    • 原因是: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
    • 这是启发式

  3. Choose a row r  such that A rc  = 1 (nondeterministically ).
  4. Include row r  in the partial solution.
  5. For each column j  such that A rj  = 1,for each row i  such that A ij  = 1,delete row i  from matrix A ;delete column j  from matrix A .
  6. 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 数据结构详解 #### 一、概述 **ACM Dancing Link**(简称 DLX)是一种高效解决**精确覆盖问题**的数据结构。它在实际应用中特别适用于解决诸如**数独**这类问题,其核心思想是通过双向链表...

    DancingLink acm 算法 跳表

    标题中的"DancingLink acm 算法 跳表"是三种不同的数据结构或算法技术,它们在解决特定问题时都有其独特的作用。这里分别介绍这三个概念: 1. **DancingLink算法**:Dancing Links(舞动链接)是由Donald Knuth提出...

    解数独——dancing link X

    解数独问题属于计算机科学中的算法问题,而dancing links是一种用于优化算法效率的技术。Donald E. Knuth 是一位著名的计算机科学家,他提出的dancing links方法在实现算法,尤其是解决类似于数独这样的约束满足问题...

    DancingLink

    ### DancingLinks:优化搜索问题的高效算法 #### DancingLinks是什么? DancingLinks,直译为“跳舞链接”,是由Donald Knuth在2000年左右提出的一种数据结构和算法技术,主要用于解决一类特殊的搜索问题——确切...

    dancing links 骑士遍历

    标题所蕴含的知识点是"Dancing Links 解决骑士遍历问题"。"Dancing Links"是指X算法的一种实现方式,即通过链表的数据结构解决精确覆盖问题。在此问题中,骑士遍历问题即马踏棋盘问题,是该算法的一个应用场景。该...

    浙江省第6届 ACM大学生程序设计竞赛解题报告(作者:曹鹏)

    浙江省第6届 ACM大学生程序设计竞赛解题报告 本文是 浙江省第6届 ACM大学生程序设计竞赛的解题报告,由曹鹏所著。该报告涵盖了竞赛中的11道题目,涵盖了... Treasure Map:该题是最难的题目,需要使用 dancing link。

    ACM模板byXYM

    #### 4.7 Dancing Link 用于解决精确覆盖问题。 ### 五、计算几何 计算几何部分涉及了众多几何对象的定义、性质和算法: #### 5.1 各种公式 包括计算距离、角度等。 #### 5.2 基本类型定义 定义了几何对象的基本...

    Sudoku:用 Java UI 计算数独问题

    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自动机 个人模板与说明

    在下曾学习于 AC自动机详细讲解 必备技能: trie + KMP 文章目录1. 结构体2. 添加模式串3. 求失配指针4. 匹配文本串ends:模板1 统计出现的模式串个数ends:模板2 统计出现次数最多的模式串(带初始化)ends:模板3 ...

    dangcing link(大师手笔,Knuth的一篇文章)

    标题与描述中的“Dancing Links”(舞动链接)是一种数据结构操作技术,由计算机科学领域的传奇人物Donald E. Knuth在2000年提出。该技术特别适用于解决回溯算法中的问题,如N皇后问题等。Knuth在文章中强调了这种...

    智慧拼珠求解及智慧金字塔求解

    本话题主要探讨的是"智慧拼珠求解"与"智慧金字塔求解"这两种问题,以及它们对应的解决方案——回溯法和Dancing Links算法。下面将详细阐述这两个概念及其应用。 首先,让我们了解"智慧珠"。智慧珠是一种典型的组合...

    智慧拼图(钻石形)

    - 数据结构:Dancing Links 是一种基于链表的特殊数据结构,其中每个元素都有四个链接,分别指向相邻的元素和相对元素。 - 压缩表示:拼图的状态可以压缩为一个二维数组,表示各个位置的块是否已放置。 - 搜索...

    gba-remote-play:通过链路电缆将 Raspberry Pi 游戏流式传输到 GBA

    : 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 所有...

    AE中英对照.docx

    "Dancing Dissolve"则是动态溶解,增加了过渡的动态效果,使画面更富有趣味性。"Darken"表示变暗,"Multiply"代表正片叠底,这种混合模式可以使底层颜色变暗,常用于实现图像的叠加效果。"Color Burn"是颜色加深,...

    AngularJS使用ngOption实现下拉列表的实例代码

    这个指令使得我们可以轻松地...&lt;link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css"&gt; &lt;script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt; ...

    数据结构Advanced-Data-Structures

    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 ...

    英语语法专题名词和冠词PPT课件.pptx

    3. 主 + 系 + 表 (S+Link.V+C):如 "They are heroes." 这里"are"是系动词,"heroes"是表语,描述主语的特性。 4. 主 + 谓 + 双宾 (S+Vt+InO+DO):如 "I offered him 5 dollars." 这里有直接宾语"him"和间接宾语"5 ...

    ffmpeg用filter添加水印

    然后,你可以通过`avfilter_link`函数连接输入和输出过滤器,使得视频流能够通过过滤器链路。 3. **初始化和配置上下文**:在开始处理视频之前,需要初始化`AVCodecContext`并设置合适的编解码器参数。这包括设置...

Global site tag (gtag.js) - Google Analytics