• 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;
    }
  • 相关阅读:
    centos7安装rlwrap
    Linux CentOS 7的图形界面安装(GNOME、KDE等)
    在oracle下我们如何正确的执行数据库恢复
    Viewer.js 图片预览插件使用
    深拷贝和浅拷贝
    ES6 export,import报错
    Yarn 命令详解
    npm命令 VS yarn命令
    Windows下nginx作为静态资源服务器使用
    关于Vue脚手架写法的问题
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/2971446.html
Copyright © 2020-2023  润新知