码迷,mamicode.com
首页 > 其他好文 > 详细

Dancing links

时间:2015-12-16 23:13:47      阅读:394      评论:0      收藏:0      [点我收藏+]

标签:

 

基本思路(Main Thoughts):

     Dancing link是一种十分优美的数据结构。

     通常配合IDA*,二分等方法解决可以转化为精确覆盖和重复覆盖的题目。

     精确覆盖:在一个01矩阵中选几行,使得这几行组合起来的矩阵每列有且只有一个1

     重复覆盖:每列可以有多个1


 

 

实现步骤(Implementation Steps):

     如果是正常的搜索

     解决步骤:

  1. 选最左边第一个没有被删除的列
  2. 选择一个在1中选出的列中有1的行,其他行直接删除
  3. 删掉2中选出的行剩余的元素所在的列
  4. 重复1,直到有一次没有可选列
  5. 如果一列没有被删除且列中已经没有元素,则回溯重新选择一行

  DLX基本上用到的就是这种思想

     辅助数组:

         R,L,U,D代表当前元素在链表中右左上下的元素

         C代表i点所在列

    S代表i列元素个数

         F,last,Last用于建表,分别是i行第一个元素,i行上一个元素,i列上一个元素。

    

  执行步骤:

    1、Dancing函数的入口

    2、判断Head.Right=Head?,若是,输出答案,返回True,退出函数。

    3、获得Head.Right的元素C

    4、标示元素C

    5、获得元素C所在列的一个元素

    6、标示该元素同行的其余元素所在的列首元素

    7、获得一个简化的问题,递归调用Daning函数,若返回的True,则返回True,退出函数。

    8、若返回的是False,则回标该元素同行的其余元素所在的列首元素,回标的顺序和之前标示的顺序相反

    9、获得元素C所在列的下一个元素,若有,跳转到步骤6

    10、若没有,回标元素C,返回False,退出函数。

  由于篇幅有限,在此贴出大神blog : http://www.cnblogs.com/grenet/p/3145800.html

  以供大家参考。

 

模板(Code):

技术分享
 1 void build()
 2 {
 3     L[0]=m,R[m]=0;
 4     for(int i=1;i<=m;i++)
 5     {
 6         R[i-1]=i;
 7         L[i]=i-1;
 8         c[i]=0,r[i]=i;
 9         s[i]=0;d[i]=f[i]=last[i]=0;
10     }
11 } 
12  
13 void del(int CC)
14 {
15     L[R[CC]]=L[CC],R[L[CC]]=R[CC];
16     for(int i=D[CC];i!=CC;i=D[i])
17     for(int j=R[i];j!=i;j=R[j])
18         U[D[j]]=U[j],D[U[j]]=D[j],s[c[j]]--;
19 }
20  
21 void add(int CC)
22 {
23     R[L[CC]]=CC,L[R[CC]]=CC;
24     for(int i=U[CC];i!=CC;i=U[i])
25     for(int j=L[i];j!=i;j=L[j])
26         U[D[j]]=j,D[U[j]]=j,s[c[j]]++;
27 }
28  
29 bool search(int k)
30 {
31     if(R[0]==0)
32     {
33         printf("%d",k);
34         for(int i=1;i<=k;i++)
35             printf(" %d",r[ans[i]]);
36         printf("\n");
37         return 1;
38     }
39     int mn=999999,C;
40     for(int i=R[0];i;i=R[i])
41         if(mn>s[i])mn=s[i],C=i;
42     del(C);
43     for(int i=D[C];i!=C;i=D[i])
44     {
45         ans[k+1]=i;
46         for(int j=R[i];j!=i;j=R[j])del(c[j]);
47         if(search(k+1))return 1;
48         for(int j=L[i];j!=i;j=L[j])add(c[j]);
49     }
50     add(C);
51     return 0;
52 }
53  
54 void link(int row,int col)
55 {
56     size++;
57     s[col]++;
58             if(!last[row])last[row]=size,R[size]=size,L[size]=size,f[row]=size;
59     else L[size]=last[row],R[last[row]]=size,last[row]=size,R[size]=f[row],L[f[row]]=size;
60     if(!d[col])d[col]=size,D[col]=size,U[size]=col,U[col]=size,D[size]=col;
61     else U[col]=size,D[size]=col,U[size]=d[col],D[d[col]]=size,d[col]=size;
62     r[size]=row,c[size]=col;
63 }    
View Code

 

时间&空间复杂度(Time & Memory Complexity):

     空间:O(?)

     时间:O(?)

主要用途&优缺点(Main Applications & Advantages & Disadvantages):

  主要用途: 通常配合IDA*,二分等方法解决可以转化为精确覆盖和重复覆盖的题目。

       优点:快

       缺点:长

推荐题目&数据(Recommendatory Problems & Data) :

     Hustoj 1017 裸的精确覆盖

     UVA 1603 破坏正方形 DLX重复覆盖

 

 

Dancing links

标签:

原文地址:http://www.cnblogs.com/tuigou/p/5052570.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!