精确覆盖DLX算法模板另一种写法

代码

struct DLX
{
    int n,id;
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int C[maxn],S[maxn],loc[maxn][2];
    int H[ms];
    void init(int nn=0) //传列长
    {
        n=nn;
        for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1;
        L[0]=n; R[n]=0;
        id=n;
        memset(S,0,sizeof(S));
        memset(H,-1,sizeof(H));
    }
    void Link(int x,int y)
    {
        ++id;
        D[id]=y; U[id]=U[y];
        D[U[y]]=id; U[y]=id;
        loc[id][0]=x,loc[id][1]=y;
        C[id]=y; S[y]++;
        if(H[x]==-1) H[x]=L[id]=R[id]=id;
        else
        {
            int a=H[x];
            int b=R[a];
            L[id]=a; R[a]=id;
            R[id]=b; L[b]=id;
            H[x]=id;
        }
    }
    void Remove(int Size)
    {
        for(int j=D[Size];j!=Size;j=D[j])//将左右两边连接
            L[R[j]]=L[j],R[L[j]]=R[j];
    }
    void Resume(int Size)
    {
        for(int j=U[Size];j!=Size;j=U[j])//恢复
            L[R[j]]=R[L[j]]=j;
    }
    bool vis[ms];//标记行是否访问过
    int h() //启发式函数
    {
        int ret=0;
        int i,j,k;
        memset(vis,0,sizeof(vis));
        for(i=R[0];i;i=R[i])
        {
           if(vis[i]) continue;
           ret++;
           for(j=D[i];j!=i;j=D[j]) //所有关联的标记了
               for(k=R[j];k!=j;k=R[k]) vis[C[k]]=1;
        }
        return ret;
    }
    void dfs(int step)
    {
        if(step+h()>=ans) return;
        if(R[0]==0){ ans=min(ans,step); return; }
        int Min=INF,c=-1;
        for(int i=R[0];i;i=R[i]) if(Min>S[i]){ Min=S[i]; c=i; }
        for(int i=D[c];i!=c;i=D[i])
        {
            Remove(i);
            for(int j=R[i];j!=i;j=R[j]) Remove(j);
            dfs(step+1);
            for(int j=L[i];j!=i;j=L[j]) Resume(j);
            Resume(i);
        }
        return;
    }
}dlx;

时间: 2024-08-04 15:30:09

精确覆盖DLX算法模板另一种写法的相关文章

精确覆盖DLX算法模板

代码 struct DLX { int n,id; int L[maxn],R[maxn],U[maxn],D[maxn]; int C[maxn],S[maxn],loc[maxn][2]; void init(int nn=0) //传列长 { n=nn; for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1; L[0]=n; R[n]=0; id=n; memset(S,0,sizeof(S)); } void AddRow(int x,i

zoj - 3209 - Treasure Map(精确覆盖DLX)

题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形可以恰好组成这个 n x m 的大矩形. 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3372 -->>这是精确覆盖问题,而DLX正是解决精确覆盖问题的有利武器.. 模型转换:将原矩形变成一行,作为 DLX 中的列,表示要

LA 2659 &amp;&amp; poj 3076 &amp;&amp; zoj 3122 Sudoku(精确覆盖 + DLX)

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=660 TimeLimit: 3.000 seconds A Sudoku grid is a 16 x 16 grid of cells grouped in sixteen 4 x 4 squares, where some cells are filled wit

DLX精确覆盖与重复覆盖模板题

hihoCoder #1317 : 搜索四·跳舞链 原题地址:http://hihocoder.com/problemset/problem/1317 时间限制:10000ms 单点时限:1000ms 内存限制:256MB   描述 小Ho最近遇到一个难题,他需要破解一个棋局. 棋局分成了n行,m列,每行有若干个棋子.小Ho需要从中选择若干行使得每一列有且恰好只有一个棋子. 比如下面这样局面: 其中1表示放置有棋子的格子,0表示没有放置棋子. 对于上面这个问题,小Ho经过多次尝试以后得到了解为选

最新版dlx模板(精确覆盖+重复覆盖)

以前的代码太挫了,重新整理dlx,学习HH把精确覆盖,重复覆盖整合在一起. 代码: struct DLX{ const static int maxn=20010; #define FF(i,A,s) for(int i = A[s];i != s;i = A[i]) int L[maxn],R[maxn],U[maxn],D[maxn]; int size,col[maxn],row[maxn],s[maxn],H[maxn]; bool vis[70]; int ans[maxn],cnt;

SPOJ 1771&amp;&amp;DLX精确覆盖,重复覆盖

DLX的题,做过这题才算是会吧. 这道题转化成了精确覆盖模型来做,一开始,只是单纯的要覆盖完行列和斜线,WA. 后来醒悟了,不能这样,只要覆盖全部行或列即可.虽然如此,但某些细节地方很关键不能考虑到. 特别要注意的是 for(int i=R[c];i;i=R[i]){ if(i>ne) break; if(S[i] < S[c]) c = i;} 找最小值只能是在ne之前,为什么呢?因为我们要完全覆盖行.可行吗?可行.稍微留意一下DLX的模板就知道,它其实在选中一列之后,是会枚举列上的行值,

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

跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题 转:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合呢?我们采用回溯法 矩阵1: 先假定选择第1行,如下所示: 如上图中所示,红色的那行是选中的一行,这一行中有3个1,分别是第3.5.

ZOJ 3209 Treasure Map(DLX精确覆盖)

Your boss once had got many copies of a treasure map. Unfortunately, all the copies are now broken to many rectangular pieces, and what make it worse, he has lost some of the pieces. Luckily, it is possible to figure out the position of each piece in

[DLX精确覆盖+打表] hdu 2518 Dominoes

题意: 就是给12种图形,旋转,翻折.有多少种方法构成n*m=60的矩形 思路: 裸的精确覆盖.就是建图麻烦 个人太挫,直接手写每一个图形的各种形态 须要注意的是最后的答案须要除以4 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #include"queue" #include"map