hust 1017( dancing links)

第一道DLX 的题, 算是模板题吧。 

看了很久的论文才看懂, 双向十字链表第一次写还是有点纠结。 但是耐心点还是没有问题的。

搜素的优化,感觉这个超高效率的优化应该可以应用在很多方面。 在实现的过程中还有一个需要注意的东西,就是remove 和resume  要对称,不然就可能导致时间很慢或错误。。。

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define N 111000
#define INF 0x3fffffff

int n,m;
int g[1010][1010];
int u[N],d[N],r[N],l[N],c[N],line[N],ans[1010],num[1010];
int head;
int tflag;

/////////////
int tg[1010][1010];
int why=0;

void remove(int s)
{
    why++;
    r[l[s]]=r[s];
    l[r[s]]=l[s];
    for(int i=d[s];i!=s;i=d[i])
    {
        for(int j=r[i];j!=i;j=r[j])
        {
            num[c[j]]--;
            u[d[j]]=u[j];
            d[u[j]]=d[j];
        }
    }
}

void resume(int s)
{
    why++;
    r[l[s]]=s;
    l[r[s]]=s;
    for(int i=u[s];i!=s;i=u[i])
    {
        for(int j=l[i];j!=i;j=l[j])
        {
            num[c[j]]++;
            u[d[j]]=j;
            d[u[j]]=j;
        }
    }
}

void print()
{
    memset(tg,0,sizeof(tg));
    for(int i=r[head];i!=head;i=r[i])
        {
            for(int j=d[i];j!=i;j=d[j])
            {
                tg[line[j]][c[j]]=1;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%d ",tg[i][j]);
            printf("\n");
        }
}

int dfs(int s)
{
    if(tflag==1) return 1;
    if(r[head]==head)
    {
        tflag=1;
        printf("%d ",s);
        for(int i=0;i<s;i++)
            printf("%d ",ans[i]);
        return 1;
    }
    int mi=INF;
    int u1;
    for(int i=r[head];i!=head;i=r[i])
    {
        if(num[i]< mi)
        {
            mi=num[i];
            u1=i;
        }
    }
    remove(u1);
    //print();
    for(int i=d[u1];i!=u1;i=d[i])
    {
        ans[s] = line[i];
        for(int j=r[i];j!=i;j=r[j])
        {
            remove(c[j]);
            //print();
        }
        if( dfs(s+1) == 1 ) return 1;
        for(int j=l[i];j!=i;j=l[j])
            resume(c[j]);
    }
    resume(u1); // 回复时与顺序无关...
    return 0;
}


int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tflag=0;
        memset(ans,-1,sizeof(ans));
        memset(g,-1,sizeof(g));
        int id=1;
        head=0;
        r[0]=0; l[0]=0;
        int tmp=0;
        for(int i=1;i<=m;i++)
        {
            c[id]=i;
            l[id]=tmp;
            r[id]=r[tmp];
            r[tmp]=id;
            l[head]=id;
            tmp=id;
            id++;
        }
        for(int i=1;i<=n;i++)
        {
            int thead=-1;
            int cnt;
            scanf("%d",&cnt);
            tmp=-1;
            for(int j=0;j<cnt;j++)
            {
                int pos;
                scanf("%d",&pos);
                g[i][pos]=id;
                line[id]=i;
                if(thead==-1)
                {
                    thead=id;
                    tmp=id;
                    l[tmp]=tmp;
                    r[tmp]=tmp;
                }
                else
                {
                    l[id]=tmp;
                    r[id]=r[tmp];
                    r[tmp]=id;
                    l[thead]=id;
                    tmp=id;
                }
                tmp=id;
                id++;
            }
        }
        ///////////////////////
        
        for(int j=1; j<=m ;j++)
        {
            int tcnt=0;
            int thead=j;
            int tid;
            u[thead]=thead;
            d[thead]=thead;
            tmp=thead;
            for(int i=1 ; i<=n ; i++)
            {
                if(g[i][j]!=-1)
                {
                    tcnt++;
                    tid=g[i][j];
                    u[tid]=tmp;
                    d[tid]=d[tmp];
                    d[tmp]=tid;
                    u[thead]=tid;
                    tmp=tid;
                    c[tid]=j;
                }
            }
            num[j]=tcnt; // 这一列有多少元素...
        }
        /////////////////////////

        int flag = dfs(0);
        if(flag==0) printf("NO\n");
        else
        {
            printf("\n");
        }

        printf("why=%d\n",why);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chenhuan001/p/2971446.html