• POJ3740 Easy Finding 舞蹈链 DLX


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解

    题目

    精确覆盖问题模板题

    算法

    DLX算法

    学习DLX算法--传送门

    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=16+5,M=300+5;
    struct X{
        int L,R,U,D,Col,Row;
    }p[N*M];
    int n,m;
    int g[N][M],C[M],cnt=0;
    bool flag=0;
    void Delete(int k){
        p[p[k].R].L=p[k].L;
        p[p[k].L].R=p[k].R;
        for (int i=p[k].D;i!=k;i=p[i].D)
            for (int j=p[i].R;j!=i;j=p[j].R){
                C[p[j].Col]--;
                p[p[j].U].D=p[j].D;
                p[p[j].D].U=p[j].U;
            }
    }
    void Reset(int k){
        p[p[k].L].R=k;
        p[p[k].R].L=k;
        for (int i=p[k].U;i!=k;i=p[i].U)
            for (int j=p[i].L;j!=i;j=p[j].L){
                C[p[j].Col]++;
                p[p[j].U].D=j;
                p[p[j].D].U=j;
            }
    }
    bool DLX(){
        if (p[0].R==0)
            return true;
        int k=p[0].R;
        for (int i=p[k].R;i!=0;i=p[i].R)
            if (C[i]<C[k])
                k=i;
        Delete(k);
        for (int i=p[k].D;i!=k;i=p[i].D){
            for (int j=p[i].R;j!=i;j=p[j].R)
                Delete(p[j].Col);
            if (DLX())
                return true;
            for (int j=p[i].L;j!=i;j=p[j].L)
                Reset(p[j].Col);
        }
        Reset(k);
        return false;
    }
    int main(){
        while (~scanf("%d%d",&n,&m)){
            for (int i=1;i<=n;i++)
                for (int j=1;j<=m;j++)
                    scanf("%d",&g[i][j]);
            memset(p,0,sizeof p);
            memset(C,0,sizeof C);
            for (int i=0;i<=m;i++)
                p[i].L=i-1,p[i].R=i+1,p[i].U=p[i].D=i;
            p[0].L=m,p[m].R=0,cnt=m;
            for (int i=1;i<=n;i++){
                int first=cnt+1;
                for (int j=1;j<=m;j++)
                    if (g[i][j]){
                        cnt++;
                        p[cnt].L=cnt-1;
                        p[cnt].R=cnt+1;
                        p[cnt].D=j;
                        p[p[j].U].D=cnt;
                        p[cnt].U=p[j].U;
                        p[j].U=cnt;
                        C[p[cnt].Col=j]++;
                        p[cnt].Row=i;
                    }
                if (cnt>=first)
                    p[first].L=cnt,p[cnt].R=first;
            }
            if (DLX())
                puts("Yes, I found it");
            else
                puts("It is impossible");
        }
        return 0;
    }
  • 相关阅读:
    Kostya Keygen#2分析
    一个简单的windows勒索软件分析
    MSRHook与SSDTHook
    VS2013中调驱动
    VMProtect1.63分析
    Linux内核分析总结
    进程的切换和系统的一般执行过程
    可执行程序的装载
    进程的描述和进程的创建
    扒开系统调用的三层皮(下)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/POJ3740.html
Copyright © 2020-2023  润新知