HUSTOJ1017_Exact cover _跳舞链DLX的精确覆盖
来源:互联网 发布:英制螺纹大小径算法 编辑:程序博客网 时间:2024/05/14 17:05
题意
给一个 n * m 的图,每一个格子上写着 1 或 0。要求选出一个行的集合,由这个行集合构成的子图中,每一列有且只有一个 1。输出集合元素个数并输出集合,或输出NO。
思路
第一个DLX,学到了。
这类问题的学名叫精确覆盖问题。DLX准确地讲是一种数据结构,可以高效地进行矩阵的递归和回溯。
DLX详解:http://www.cnblogs.com/grenet/p/3145800.html
kuangbin的模板:http://www.cnblogs.com/kuangbin/p/3752854.html
题目链接
http://acm.hust.edu.cn/problem/show/1017
AC代码
可以说是默写了一遍 kuangbin 的模板
#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int maxn = 1010; //最大行数 const int maxm = 1010; //最大列数 const int maxv = maxn * 100; //最大节点数 //Dancing Links 类 struct DLX{ int n, m, size; //行数、列数、节点数 int U[maxv], D[maxv], L[maxv], R[maxv], Row[maxv], Col[maxv]; //上、下、左、右指针,行、列号 int S[maxm], H[maxn]; //列的节点个数,行的头指针 int ansd, ans[maxn]; //答案栈 void init(int _n, int _m) //初始化函数 { n = _n, m = _m; for(int j= 0; j<= m; j++) { Row[j] = 0, Col[j] = j; //行、列号 U[j] = D[j] = j; //上下指针 S[j] = 0; L[j] = j - 1, R[j] = j + 1; //左右指针 } L[0] = m, R[m] = 0; //端点左右指针 size = m; //节点个数(初始 = 列数)(附加节点) for(int i= 1; i<= n; i++) //行的头指针 H[i] = -1; } void link(int r, int c) //向链表中插入节点 { size ++; //节点数目 Row[size] = r, Col[size] = c; //行号、列号 S[c] ++; //插入列链表 D[size] = D[c]; U[D[c]] = size; D[c] = size; U[size] = c; if(H[r] == -1) H[r] = L[size] = R[size] = size; //将节点插入行链表 else{ //第一个节点之后 R[size] = R[H[r]]; L[R[H[r]]] = size; L[size] = H[r]; R[H[r]] = size; } } void remove(int c) //删除列函数(同时删除列中节点所在的行) { L[R[c]] = L[c], R[L[c]] = R[c]; //列删除 for(int i= D[c]; i!= c; i= D[i]) //删除列中节点所在的行 for(int j= R[i]; j!= i; j= R[j]) { U[D[j]] = U[j], D[U[j]] = D[j]; S[Col[j]] --; } } void resume(int c) //恢复列函数(同时恢复列中节点所在的行 { R[L[c]] = L[R[c]] = c; //列恢复 for(int i= U[c]; i!= c; i= U[i]) //恢复列中节点所在的行 for(int j= L[i]; j!= i; j= L[j]) { U[D[j]] = j, D[U[j]] = j; S[Col[j]] ++; } } bool Dance(int d) //搜索函数 { if(R[0] == 0) //剩余列为空,搜索成功 { ansd = d; return true; } int c = R[0]; //从节点少的列开始搜索,可以减少状态数 for(int j= R[0]; j!= 0; j= R[j]) if(S[j] < S[c]) c = j; remove(c); //删除当前列 for(int i= D[c]; i!= c; i= D[i]) //遍历选取当前列中节点所在的行 { ans[d] = Row[i]; //行号压入答案栈 for(int j= R[i]; j!= i; j= R[j]) remove(Col[j]); //删除行中节点对应的列 if(Dance(d+1)) return true; //向下一层搜索 for(int j= L[i]; j!= i; j= L[j]) resume(Col[j]); //搜索失败的话还原当前行 } resume(c); return false; }};int n, m;DLX g;int main(){ while(cin >> n >> m) { g.init(n, m); //初始化 for(int i= 1; i<= n; i++) //构造链表 { int num; cin >> num; while(num --) { int j; cin >> j; g.link(i, j); } } if(g.Dance(0)){ //DLX printf("%d ", g.ansd); for(int i= 0; i< g.ansd; i++) printf("%d ", g.ans[i]); printf("\n"); } else printf("NO\n"); } return 0;}
阅读全文
0 0
- HUSTOJ1017_Exact cover _跳舞链DLX的精确覆盖
- 舞蹈链..Exact cover&Treasure Map等 . DLX-精确覆盖
- hust - 1017 - Exact cover(精确覆盖DLX)
- HUST 1017 Exact cover(DLX精确覆盖)
- 【HUST - 1017】精确覆盖问题 Exact Cover DLX 解题报告
- HUST - 1017 Exact cover DLX解精确覆盖问题题解
- [DLX 精确覆盖 模板题] HUST 1017 Exact cover
- 精确覆盖问题-跳舞链算法
- 初涉关于精确覆盖的DLX
- dlx 精确覆盖
- DLX精确覆盖poj1086
- DLX 精确覆盖 重复覆盖
- DLX 舞蹈链 精确覆盖+可重复覆盖
- ZOJ3209Treasure Map精确覆盖DLX
- 【精确覆盖问题】DLX算法
- DLX精确覆盖 poj2676 Sudoku
- [ZOJ]3209 Treasure Map 跳舞链 精确覆盖
- hust1017-Exact cover 舞蹈链之精确覆盖(裸的)
- UML& Rose
- 关于JavaScript中apply与call的用法意义及区别
- C#面向对象入门
- 初学C++的小蒟蒻报到
- 2017阿里秋招提前批内推编程测试题“APP启动耗时最短”
- HUSTOJ1017_Exact cover _跳舞链DLX的精确覆盖
- JDBC操作全攻略
- POJ 1847 Tram 笔记
- SQL注入与参数化查询
- jozj. 1729.blockenemy
- TextView用drawableLeft时,改变文字和图片间的距离
- 贪心(HDOJ 4221)
- 常用transformation介绍
- 《剑指offer》栈的压入、弹出序列