• poj3074 DLX精确覆盖


    题意:解数独

    分析:

    完整的数独有四个充要条件:

    1.每个格子都有填数字

    2.每列都有1~9中的每个数字

    3.每行都有1~9中的每个数字

    4.每个9宫格都有1~9中的每个数字

    可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。

    对于已经确定的点 我们就直接建一行 对于没有确定的点我们就 建k行(k<=9),这样说如果在该行该列或者该3*3的矩阵中存在该数字 则对应的该数字所在的行就没有必要建立了

    这样跑一次dlx精确覆盖就ok了

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <string.h>
    using namespace std;
    const int M=9*9*9*10*4;
    
    struct node{
       int c,x,y,k;
    };
    struct DLX
    {
            int n,sz;
            int S[9*9*5];
            int row[M],col[M];
            int L[M],R[M],U[M],D[M];
            int ans[10][10];
            int X[M],Y[M],Cnt[M];
            void init(int n)
            {
                this->n=n;
                for(int i=0; i<=n; i++)
                {
                    U[i]=i;D[i]=i;
                    L[i]=i-1; R[i]=i+1;
                }
                R[n]=0;L[0]=n;
                sz=n+1;
                memset(S,0,sizeof(S));
            }
            void addRow(int r,vector<node>columns)
            {
                int first=sz;
                for(int i=0; i<columns.size();i++)
                {
                    int c=columns[i].c; X[sz]=columns[i].x; Y[sz]=columns[i].y; Cnt[sz]=columns[i].k;
                    L[sz]=sz-1;
                    R[sz]=sz+1;
                    D[sz]=c; U[sz]=U[c];
                    D[U[c]]=sz;U[c]=sz;
                    row[sz]=r;col[sz]=c;
                    S[c]++;sz++;
                }
               R[sz-1]=first; L[first]=sz-1;
            }
            #define FOR(i,A,s) for(int i=A[s]; i!=s; i=A[i])
            void remove(int c)
            {
                L[R[c]]=L[c];
                R[L[c]]=R[c];
                FOR(i,D,c)
                FOR(j,R,i)
                {
                    U[D[j]]=U[j];D[U[j]]=D[j];--S[col[j]];
                }
            }
            void restore(int c)
            {
                FOR(i,U,c)
                FOR(j,L,i)
                {
                    ++S[col[j]];U[D[j]]=j;D[U[j]]=j;
                }
                L[R[c]]=c;
                R[L[c]]=c;
            }
            bool dfs(int d)
            {
                if(R[0]==0)return true;
                else
                {
                    int num=R[0];
                    FOR(i,R,0)
                    {
                       if(S[i]==0) return false;
                       if(S[num]>S[i])
                        {
                            num=i;
                        }
                    }
                    remove(num);
                    FOR(i,D,num)
                    {
                        ans[X[i]][Y[i]]=Cnt[i];
                        FOR(j,R,i)remove(col[j]);
                        if(dfs(i+1))
                        {
                           return true;
                        }
                        FOR(j,L,i)restore(col[j]);
                    }
                    restore(num);
                    return false;
                }
            }
    }Link;
    bool hasr[10][10],hasc[10][10],hasp[10][10];
    char str[100];
    vector<node> colum;
    int main()
    {
        while(scanf("%s",str)==1&&str[0]!='e')
        {
            memset(hasr,false,sizeof(hasr));
            memset(hasc,false,sizeof(hasc));
            memset(hasp,false,sizeof(hasp));
            for(int i=0; i<9; i++)
                for(int j=0; j<9; j++)
                {
                    if(str[i*9+j]!='.')
                    {
                        int k=str[i*9+j]-'0';
                        hasr[i][k]=true;
                        hasc[j][k]=true;
                        hasp[i/3 *3+j/3][k]=true;
                    }
                }
            int m=4*9*9;
            int n=0;
            Link.init(m);
            for(int i=0; i<9; i++)
                for(int j=0; j<9; j++)
                {
                    int k=0;
                    if(str[i*9+j]!='.')
                        k=str[i*9+j]-'0';
                    if(k!=0)
                    {
                        n++;
                        colum.clear();
                        node dot;
                        dot.k=k;
                        dot.x=i;
                        dot.y=j;
                        dot.c=i*9+j+1;
                        colum.push_back(dot);
                        dot.c=81+i*9+k;
                        colum.push_back(dot);
                        dot.c=162+j*9+k;
                        colum.push_back(dot);
                        dot.c=243+(i/3*3+j/3)*9+k;
                        colum.push_back(dot);
                        Link.addRow(n,colum);
                    }else {
                        node dot;
                        dot.x=i;dot.y=j;
                        for(int k=1; k<=9; k++)
                        {
                            if(hasr[i][k]==false &&hasc[j][k]==false && hasp[i/3*3+j/3][k]==false)
                            {
                                dot.k=k;
                                colum.clear();
                                n++;
                                dot.c=i*9+j+1;
                                colum.push_back(dot);
                                dot.c=81+i*9+k;
                                colum.push_back(dot);
                                dot.c=162+j*9+k;
                                colum.push_back(dot);
                                dot.c=243+(i/3*3+j/3)*9+k;
                                colum.push_back(dot);
                                Link.addRow(n,colum);
                            }
                        }
    
    
                    }
    
                }
                Link.dfs(0);
                for(int i=0; i<9;i++)
                   for(int j=0; j<9; j++)
                     printf("%d",Link.ans[i][j]);
                puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)
    bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
    spoj 375 Query on a tree(树链剖分,线段树)
    bzoj 2618 2618: [Cqoi2006]凸多边形(半平面交)
    C++中int型与char型相互转换的问题
    408 二进制求和
    407 加一
    斐波那契数列几种算法及时间复杂度分析
    397 Longest Continuous Increasing Subsequence
    376 二叉树的路径和
  • 原文地址:https://www.cnblogs.com/Opaser/p/4685380.html
Copyright © 2020-2023  润新知