hdu4069 Squiggly Sudoku

来源:互联网 发布:淘宝店铺评估 编辑:程序博客网 时间:2024/06/13 03:10

        解一个9*9的数独,行和列和普通数独一样需要出现1~9,但是它的小区域不是方形的,而是一个不规则的面积为9的图形。

        DLX模版题。位运算和dfs处理小区域的边界就不说了。DLX搜解,搜到一个解以后继续搜,如果搜到第二个解则说明有多解,立即跳出。需要注意的是,搜到第一个解以后,需要保存解,不然继续搜索原来的解会被破坏。


#include <stdlib.h>#include <iostream>#include <stdio.h>#include <string.h>#include <vector>using namespace std;     #define ll long long  const int SLOT = 0;const int ROW = 1;const int COL = 2;const int SUB = 3;int encode(int type,int id,int num){    return type*81+(id-1)*9+num;}int mp[12][12];int sub[12][12];const int maxnode=270000;const int maxn=350;const int maxr=750;int anscnt;void init(){    anscnt=0;    memset(sub,0,sizeof(sub));}struct dlx{#define FOR(i,A,s) for(int i = A[s];i!=s;i=A[i])    int n,sz;    int U[maxnode],D[maxnode],L[maxnode],R[maxnode];    int row[maxnode],col[maxnode];        int S[maxn];    //各列节点数     int ans[maxr];    int ans2[maxr];    int ansdep;        void init(int n){        this->n=n;        sz=0;        memset(S,0,sizeof(S));                for(int i=0;i<=n;i++){            U[i]=D[i]=i;            L[i]=i-1;    R[i]=i+1;            sz++;        }        L[0]=n;    R[n]=0;    }        void addrow(int r,vector<int> newrow){        int first=sz;        for(int i=0;i<newrow.size();i++){            int pos=newrow[i];            U[sz]=U[pos];    D[sz]=pos;            U[pos]=sz;            D[U[sz]]=sz;            row[sz]=r;            col[sz]=pos;            S[pos]++;            sz++;                }        for(int i=first;i<sz;i++){            L[i]=i-1;    R[i]=i+1;        }        L[first]=sz-1;    R[sz-1]=first;    }        void remove(int c){        R[L[c]]=R[c];        L[R[c]]=L[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;            }        }        R[L[c]]=c;        L[R[c]]=c;    }        void dfs(int d){        if(anscnt>1)return;        if(R[0]==0){            ansdep=d;            anscnt++;            memcpy(ans2,ans,sizeof(ans));            return;        }                int c=R[0];    //去满足一列         for(int i=c;i!=0;i=R[i]){            if(S[i]<S[c])c=i;        }        remove(c);        FOR(i,D,c){    //遍历这一列             ans[d]=row[i];            FOR(j,R,i){                remove(col[j]);            }            dfs(d+1);            FOR(j,L,i){                restore(col[j]);            }        }        restore(c);    }    }solver;void dfs(int nn,int mm,int val){    //找上下左右    //u16 r32 d64 l128    if(sub[nn][mm])return;    sub[nn][mm]=val;    if( (mp[nn][mm]&16)==0){        dfs(nn-1,mm,val);    }    if( (mp[nn][mm]&32)==0){        dfs(nn,mm+1,val);    }    if( (mp[nn][mm]&64)==0){        dfs(nn+1,mm,val);    }    if( (mp[nn][mm]&128)==0){        dfs(nn,mm-1,val);    }    }int main(){    int t;    cin>>t;    int cas=0;    while(t--){        init();    cas++;        for(int i=1;i<=9;i++){            for(int j=1;j<=9;j++){                scanf("%d",&mp[i][j]);            }        }                int subcnt=0;        for(int i=1;i<=9;i++){            for(int j=1;j<=9;j++){                if(!sub[i][j]){                    dfs(i,j,++subcnt);                }            }        }        //        for(int i=1;i<=9;i++){            for(int j=1;j<=9;j++){                mp[i][j]&=15;            }        }                solver.init(324);                for(int i=1;i<=9;i++){            for(int j=1;j<=9;j++){                for(int k=1;k<=9;k++){                    if(mp[i][j]==k||mp[i][j]==0){                        vector<int> vec;                        vec.push_back(encode(SLOT,i,j));                        vec.push_back(encode(ROW,i,k));                        vec.push_back(encode(COL,j,k));                        vec.push_back(encode(SUB,sub[i][j],k));                        solver.addrow( (i-1)*81+(j-1)*9+(k-1) ,vec);                    }                }            }        }                solver.dfs(0);                printf("Case %d:\n",cas);        if(anscnt==0){            printf("No solution\n");        }else if(anscnt==1){            for(int i=0;i<81;i++){                int tmp=solver.ans2[i];                int nn=tmp/81;                tmp-=nn*81;                int mm=tmp/9;                int val=tmp%9;                mp[nn+1][mm+1]=val+1;            }            for(int i=1;i<=9;i++){                for(int j=1;j<=9;j++){                    printf("%d",mp[i][j]);                }printf("\n");            }        }else{            printf("Multiple Solutions\n");        }    }    return 0;}



0 0
原创粉丝点击