Dancing Links用来解决如下精确匹配的问题:

选择若干行使得每一列恰好有一个1。Dancing Links通过对非零元素建立双向十字循环链表。上面的例子建立的链表如下所示:

计算的时候使用搜索的策略。每次选出1最少的一列,比如c,然后选择这一列中的某一行,比如r,(r,c)=1,然后r中所有1所在的列,那些其他行这些列有1的都删掉(这些行不会在r算入答案后也在答案里,否则就有某些列多于一个1出现)。然后这就变成一个规模更小的问题,继续搜索。无解时要回溯。

 class CDancingLinks
{
protected:
struct DancingLinksNode
{
DancingLinksNode* left;
DancingLinksNode* right;
DancingLinksNode* down;
DancingLinksNode* up;
int col;
int row;
}; typedef DancingLinksNode Node; int *m_columnEleNumbers;
int m_colNumber;
int m_rowNumber;
Node* m_pool;
Node** m_head;
int m_curUsePoolIndex; void _Remove(Node* cur)
{
--m_columnEleNumbers[cur->col];
for(Node* p=cur->down;p!=cur;p=p->down)
{
p->left->right=p->right;
p->right->left=p->left;
}
} void _Resume(Node* cur)
{
++m_columnEleNumbers[cur->col];
for(Node* p=cur->up;p!=cur;p=p->up)
{
p->left->right=p;
p->right->left=p;
}
} bool _SearchSolution(const int depth,std::vector<int> &solution)
{
Node* p=_GetNode();
if(p->left==p) return true; int Min=m_rowNumber+;
int MinColumnIndex=;
for(Node* q=p->left;q!=p;q=q->left)
{
if(m_columnEleNumbers[q->col]<Min)
{
Min=m_columnEleNumbers[q->col];
MinColumnIndex=q->col;
}
} for(Node* q=_GetNode(MinColumnIndex)->down;q!=_GetNode(MinColumnIndex);q=q->down)
{
_Remove(q);
solution.push_back(q->row);
for(Node* rr=q->right;rr!=q;rr=rr->right) _Remove(rr);
if(_SearchSolution(depth+,solution)) return true;
for(Node* rr=q->left;rr!=q;rr=rr->left) _Resume(rr);
solution.pop_back();
_Resume(q);
} return false;
} Node* _GetNode(int id) { return m_pool+id; } void _ReleaseMemory()
{
if(m_columnEleNumbers)
{
delete[] m_columnEleNumbers;
m_columnEleNumbers=nullptr;
} if(m_pool)
{
delete[] m_pool;
m_pool=nullptr;
}
if(m_head)
{
delete[] m_head;
m_head=nullptr;
}
} public: CDancingLinks():m_colNumber(-),m_rowNumber(-),
m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr) {} /***
列下标为[1,Column]
***/
CDancingLinks(const int Column,const int Row):
m_columnEleNumbers(nullptr),m_pool(nullptr),m_head(nullptr)
{
SetSize(Column,Row);
} /***
列下标为[1,Column]
***/
void SetSize(const int Column,const int Row)
{
m_colNumber=Column;
m_rowNumber=Row; _ReleaseMemory(); m_columnEleNumbers=new int[m_colNumber+];
m_pool=new Node[m_colNumber*(m_rowNumber+)+];
m_head=new Node*[m_rowNumber+];
Clear();
} void Clear()
{
for(int i=;i<=m_colNumber;++i)
{
Node* cur=_GetNode(i);
cur->left=((i==m_colNumber)?_GetNode():_GetNode(i+));
cur->right=((==i)?_GetNode(m_colNumber):_GetNode(i-));
m_columnEleNumbers[i]=; cur->up=cur->down=_GetNode(i);
cur->col=i;
cur->row=;
}
for(int i=;i<=m_rowNumber;++i) m_head[i]=NULL;
m_curUsePoolIndex=m_colNumber+;
} ~CDancingLinks()
{
_ReleaseMemory();
} void AddElement(const int row,const int col)
{ Node* cur=m_pool+(m_curUsePoolIndex++); cur->up=_GetNode(col);
cur->down=_GetNode(col)->down;
m_pool[col].down->up=cur;
m_pool[col].down=cur; if(m_head[row]==NULL)
{
m_head[row]=cur->left=cur->right=cur;
}
else
{
cur->left=m_head[row]->left;
cur->right=m_head[row];
m_head[row]->left->right=cur;
m_head[row]->left=cur;
}
++m_columnEleNumbers[col];
cur->col=col;
cur->row=row;
} bool GetSolution(std::vector<int> &Solution)
{
return _SearchSolution(,Solution);
}
};

Dancing Links的更多相关文章

  1. Dancing Links and Exact Cover

    1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...

  2. 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

    精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...

  3. ZOJ 3209 Treasure Map (Dancing Links)

    Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 KB Your boss once had got many copies of ...

  4. HUST 1017 - Exact cover (Dancing Links 模板题)

    1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...

  5. Dancing Links初学记

    记得原来备战OI的时候,WCX大神就研究过Dancing Links算法并写了一篇blog.后来我还写了个搜索策略的小文章( http://www.cnblogs.com/pdev/p/3952279 ...

  6. 【转】Dancing Links题集

    转自:http://blog.csdn.net/shahdza/article/details/7986037 POJ3740 Easy Finding [精确覆盖基础题]HUST1017 Exact ...

  7. 【转】Dancing Links精确覆盖问题

    原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文    精确覆盖问题    解决精确覆盖问题    舞蹈步骤    效率分析 ...

  8. POJ 3074 Sudoku (Dancing Links)

    传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...

  9. HDU5046 Airport dancing links 重复覆盖+二分

    这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...

随机推荐

  1. 夺命雷公狗ThinkPHP项目之----企业网站11之栏目的删除完成

    我们删除要在分类模型中添加一个_before_delete的钩子函数,而且在删除一个分类时候,如果这个分类有子分类就不允许删除 model层代码如下所示: <?php namespace Adm ...

  2. mysql笔记02 创建高性能的索引

    创建高性能的索引 1. 索引(在MySQL中也叫做"键(key)")是存储引擎用于快速找到记录的一种数据结构. 2. 索引可以包含一个或多个列的值.如果索引包含多个列,那么列的顺序 ...

  3. linux设备驱动归纳总结(五):4.写个简单的LED驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-84693.html linux设备驱动归纳总结(五):4.写个简单的LED驱动 xxxxxxxxxxx ...

  4. linux设备驱动归纳总结(四):3.抢占和上下文切换【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-65711.html linux设备驱动归纳总结(四):3.抢占和上下文切换 xxxxxxxxxxxxx ...

  5. 160907、CSS 预处理器-Less

    CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题: 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器: ...

  6. Linux之sed命令详解

    简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的 ...

  7. 使用SQLServer Profiler侦测死锁(转)

    准备工作: 为了侦测死锁,我们需要先模拟死锁.本例将使用两个不同的会话创建两个事务. 步骤: 1. 打开SQLServer Profiler 2. 选择[新建跟踪],连到实例. 3. 然后选择[空白] ...

  8. 20145227 《Java程序设计》第4周学习总结

    20145227 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 6.1 何谓继承 1.继承共同行为 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, ...

  9. 有三个线程T1 T2 T3,如何保证他们按顺序执行-转载

    T3先执行,在T3的run中,调用t2.join,让t2执行完成后再执行t3 在T2的run中,调用t1.join,让t1执行完成后再让T2执行 public class Test { // 1.现在 ...

  10. sass初步认识2

    sass可以使用变量,采用 $ 来进行变量声明,格式为: $highlight-color:#f90;(声明方式和css属性声明类似.使用的变量名可以更加语义化) 与js分为全局变量和局部变量类似,s ...