POJ 3074 Sudoku 精确覆盖构造

#include <stdio.h>
#include <string.h>

using namespace std;
struct DLX
{
    const static int maxn=750,maxm=350,maxnode=maxn*maxm;
    int n,m,sz,anssz;
    int u[maxnode],d[maxnode],l[maxnode],r[maxnode],row[maxnode],col[maxnode];
    //row col 记录该节点i坐标
    int h[maxn],colcnt[maxm]; //排头及列节点计数
    int ans[maxn];
    void init(int _n,int _m) //数据位于1,1...n,m
    {
        n=_n,m=_m;
        for(int i=0;i<=m;i++)//1..m是每一列的辅助结点 0代表(0,0)即head
        {
            u[i]=d[i]=i;
            l[i]=i-1;r[i]=i+1;
            col[i]=i;row[i]=0;
            colcnt[i]=0;
        }
        l[0]=m;r[m]=0;
        sz=m;anssz=0;
        for(int i=1;i<=n;i++)h[i]=-1;
    }
    inline void push(int x,int y)
    {
        colcnt[y]++;
        col[++sz]=y;
        row[sz]=x;
        d[sz]=d[y]; //加入列首元素后面
        u[sz]=y;
        u[d[y]]=sz;
        d[y]=sz;
        if(h[x]<0) h[x]=r[sz]=l[sz]=sz; //成为行首元素
        else{
            int hd=h[x]; //加入行首节点右边
            l[sz]=hd;
            r[sz]=r[hd];
            l[r[hd]]=sz;
            r[hd]=sz;
        }
    }
    inline void exact_remove(int x) //列首节点
    {
        r[l[x]]=r[x];//left's right=right
        l[r[x]]=l[x];//right's left=left
        //左右节点跳过列首节点,自己的信息依然保留
        for(int i=d[x];i!=x;i=d[i]) //删除该列占据的每一行除该列的元素的上下连接
            for(int j=r[i];j!=i;j=r[j])//,节点信息本身依然保留
            d[u[j]]=d[j],u[d[j]]=u[j],colcnt[col[j]]--;
    }
    inline void exact_resume(int x)//恢复del操作
    {
        for(int i=u[x];i!=x;i=u[i]) //注意逆操作的顺序
            for(int j=l[i];j!=i;j=l[j])
                colcnt[col[ d[u[j]] = u[d[j]] = j]]++;
        r[l[x]]=l[r[x]]=x;
    }
    bool dance(int dep)
    {
        if(r[0]==0) {
            anssz=dep;
            return true;
        }
        int cur=r[0];
        for(int i=r[0];i!=0;i=r[i])if(colcnt[i]<colcnt[cur])cur=i;
        exact_remove(cur);
        for(int i=d[cur];i!=cur;i=d[i])
        {
            ans[dep]=row[i];
            for(int j=r[i];j!=i;j=r[j]) exact_remove(col[j]);
            if(dance(dep+1)) return true;
            for(int j=l[i];j!=i;j=l[j]) exact_resume(col[j]); //注意逆操作的顺序
        }
        exact_resume(cur);
        return  false;
    }
    void preprocess()
    {
        for(int i=r[0];i;i=r[i])
            if(colcnt[i]==0) {
                l[r[i]]=l[i],r[l[i]]=r[i];
            }
    }
};
DLX dlx;
inline int encode(int a,int b,int c)
{
    return a*81+b*9+c+1;
}
inline int decode(int a,int &b,int& c,int &d)
{

    a--;
    b=a/81;
    d=a%9;
    c=a/9%9;
}
const int n=9;
int main()
{
#ifdef shuaishuai
    freopen("in.txt","r",stdin);
#endif // shuaishuai
    static char s[100];
    while(~scanf("%s",s)&&s[0]!='e')
    {
        dlx.init(encode(8,8,9),encode(3,9,9));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
        {
            char c=s[i*n+j];
            for(int k=0;k<n;k++)
                if(c=='.'||c==k+'1'){
                    int category=encode(i,j,k);
                    dlx.push(category,encode(0,i,j)); //mp[i][j]
                    dlx.push(category,encode(1,i,k)); //row k
                    dlx.push(category,encode(2,j,k)); //col k
                    dlx.push(category,encode(3,i/3*3+j/3,k)); //
                }
        }
        dlx.preprocess();
        dlx.dance(0);
        for(int i=0,sz=dlx.anssz,*a=dlx.ans,x,y,z;i<sz;i++)
        {
            decode(a[i],x,y,z);
            s[x*n+y]='1'+z;
        }
        puts(s);
    }
//    printf("%d\n",9*9*9+9*9+9);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/polya/p/9770337.html