Dancing Links的重复覆盖问题解法

     众所周知,DLX对于解决精确覆盖问题有非常出奇的效果,但我们现在考虑一种叫做重复覆盖的问题。其实这一问题是我们看到DL的论文第一部分时,对Dancing Links用法的初次想法。它就是单纯利用了链表的性质进行的模拟(请允许我这么说),但抽象而言,就是对0/1矩阵进行如下操作:选取一些行,使所有的列都有‘1’(想想与精确覆盖的不同之处)。在实现上,不需要精确覆盖的排他性操作,而在框架上的实现则是相同的。考虑一个优化,在重复覆盖问题中,对于列长是不动态计数的,能否通过初始的排序减小常数。
     以下是一般的重复覆盖问题的实现,要用到Iter-A*,使用启发函数进行加速,启发函数的设计十分简单,相信大家能看懂,此处未加过优化,如果大家有想法可以自己实现。


#include  < iostream >
#include 
< cmath >
using   namespace  std;

const   int  MAXR = 60 ;
const   int  MAXC = 60 ;
const   int  MAXLEN = MAXR * MAXC + MAXR + MAXC;
int  L[MAXLEN];
int  R[MAXLEN];
int  D[MAXLEN];
int  U[MAXLEN];
int  nRow[MAXLEN];
int  nCol[MAXLEN];

int  Col[MAXC];  // 判定列集是否已插入
int  Row[MAXR];  // 判定行集是否已插入
// int RC[MAXR][MAXC];  // 判定元素是否已插入
int  RS[MAXR],CS[MAXC];  // 行长与列长
int  eid;  // 内存标识
int  head;
int  Cn;
int  MAXSTEP;
// int ans[MAXC];
ExpandedBlockStart.gifContractedBlock.gif
/**/ /*int alen;*/

// DLX算法 进行重复覆盖
inline  void  init()
ExpandedBlockStart.gifContractedBlock.gif
{
    memset(Row,
-1,sizeof(Row));
    memset(Col,
-1,sizeof(Col));
//    memset(RC,-1,sizeof(RC));
    memset(nCol,-1,sizeof(nCol));
    memset(nRow,
-1,sizeof(nRow));
    head
=0;
    L[head]
=R[head]=D[head]=U[head]=head;
    eid
=1;
    Cn
=0;
}


// 插入行

inline 
void  insRow( int  r)
ExpandedBlockStart.gifContractedBlock.gif
{
    
    U[D[head]]
=eid;
    U[eid]
=head;
    D[eid]
=D[head];
    D[head]
=eid;
    
    L[eid]
=R[eid]=eid;
    
    RS[r]
=1;
    Row[r]
=eid++;
}


// 插入列

inline 
void  insColumn( int  c)
ExpandedBlockStart.gifContractedBlock.gif
{
    L[R[head]]
=eid;
    L[eid]
=head;
    R[eid]
=R[head];
    R[head]
=eid;
    
    U[eid]
=D[eid]=eid;
    
    CS[c]
=1;
    Col[c]
=eid++;
}


// 插入元素

inline 
void  insElement( int  r, int  c)
ExpandedBlockStart.gifContractedBlock.gif
{
    
int rid=Row[r];
    
int cid=Col[c];
    
    L[R[rid]]
=eid;
    L[eid]
=rid;
    R[eid]
=R[rid];
    R[rid]
=eid;
    
    
    U[D[cid]]
=eid;
    U[eid]
=cid;
    D[eid]
=D[cid];
    D[cid]
=eid;
    
    
    nRow[eid]
=r;
    nCol[eid]
=c;
    
    
++CS[c];
    
++RS[r];

//    RC[r][c]=eid;
    ++eid;
}


// 插入操作

inline 
void  insert( int  r,  int  c)
ExpandedBlockStart.gifContractedBlock.gif
{

    
if (Col[c]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
++Cn;
        insColumn(c);
    }


    
if(Row[r]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        insRow(r);
    }


//    if(RC[r][c]==-1)
//    {
        insElement(r,c);
//    }

}


// 删除列(使用cid)

inline 
void  RemoveCol( int  c)
ExpandedBlockStart.gifContractedBlock.gif
{
    
//c=Col[c];

    
int i;

    
for (i=U[c];i!=c;i=U[i])
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        L[R[i]]
=L[i];
        R[L[i]]
=R[i];        
    }


}


// 恢复列(使用cid)

inline 
void  ResumeCol( int  c)
ExpandedBlockStart.gifContractedBlock.gif
{
    
//c=Col[c];

    
int i;

    
for (i=D[c];i!=c;i=D[i]) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{        
        L[R[i]]
=i;
        R[L[i]]
=i;
    }


}


// 重复覆盖 iter a*

bool  hash[MAXC];

int  price()
ExpandedBlockStart.gifContractedBlock.gif
{
    
int i,j,k;
    
int ret=0;

    memset(hash,
0,sizeof(hash));

    
for (i=R[head];i!=head;i=R[i])
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
if(nCol[D[i]]==-1continue;
        
if(!hash[nCol[D[i]]])
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
++ret;
            hash[nCol[D[i]]]
=true;
            
for (j=D[i];j!=i;j=D[j])
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (nCol[j]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
continue;
                }


                
for (k=R[j];k!=j;k=R[k])
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
if (nCol[k]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
{
                        
continue;
                    }

                    hash[nCol[k]]
=true;
                }

            }

        }

    }

    
return ret;
}


inline 
bool  dfs( int  k)
ExpandedBlockStart.gifContractedBlock.gif
{
    
if (k+price()>MAXSTEP)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
return false;
    }


    
if (R[head]==head)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//alen=k;
        return true;
    }


    
int i,j;

    
int s=INT_MAX;
    
int c;

    
for (i=L[head];i!=head;i=L[i])
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
       
if(nCol[D[i]]==-1) {c=i;continue;}
        
if (CS[nCol[D[i]]]<s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            s
=CS[nCol[D[i]]];
            c
=i;
        }

    }


    
for (i=D[c];i!=c;i=D[i])
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//ans[k]=nRow[i];
        RemoveCol(i);

        
for (j=R[i];j!=i;j=R[j])
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (nCol[j]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
continue;
            }

            RemoveCol(j);
        }

        
        
if(dfs(k+1))
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return true;
        }


        
for (j=L[i];j!=i;j=L[j])
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (nCol[j]==-1)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
continue;
            }

            ResumeCol(j);
        }


        ResumeCol(i);    
    }


    
return false;
}

转载于:https://www.cnblogs.com/zhuangli/archive/2009/08/03/1537844.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值