HDU 1426 Sudoku Killer

就是把数字全填上,然后检验是否可以…… 

#include <cstdio>
#include <cstring>
#include <cmatn>
#include <algorithm>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
int a[10][10],h[10],hs[10],ss[10],nine[10],Hash[10],q[10],st=511;
int ten(int x){return (int)log2(x)+1;}
void print(){rep(i,9){rep(j,8)printf("%d ",a[i][j]);printf("%d\n",a[i][9]);}}
void dfs(int k){
    if(k==10){print();return;}
    else{
        int i=Hash[k],j,get,num,pos,p;
        pos=st&~h[i]; p=pos&-pos;
        h[i]|=p; j=ten(p);
        get=st&~(hs[i]|ss[j]|nine[(i-1)/3*3+(j-1)/3+1]);
        while(get){
            num=get&-get;
            get^=num;
            a[i][j]=ten(num);
            hs[i]|=num; ss[j]|=num;
            nine[(i-1)/3*3+(j-1)/3+1]|=num;
            if(pos==p)dfs(k+1); else dfs(k);
            hs[i]^=num; ss[j]^=num;
            nine[(i-1)/3*3+(j-1)/3+1]^=num;
        }h[i]^=p;
    }
}
int main(){
    int k=1,flag=0;char c[3];
    while(scanf("%s",c)!=EOF){
        if(flag)puts("");else flag=1;
        for(int i=0;i<10;i++)h[i]=hs[i]=ss[i]=nine[i]=Hash[i]=q[i]=0;
        if(c[0]=='?')a[1][1]=0;
        else a[1][1]=c[0]-'0';
        for(int i=1;i<=9;i++)
        for(int j=1;j<=9;j++){
            if(i==1&&j==1)continue;
            scanf("%s",c);
            if(c[0]=='?')a[i][j]=0;
            else a[i][j]=c[0]-'0';
        }
        for(int i=1;i<=9;i++)
        for(int j=1;j<=9;j++){
            Hash[i]=i;
            if(a[i][j]){
                h[i]|=1<<(j-1);
                if(((hs[i]|ss[j]|nine[(i-1)/3*3+(j-1)/3+1])&(1<<(a[i][j]-1)))==1){printf("-1\n");}
                hs[i]|=1<<(a[i][j]-1);
                ss[j]|=1<<(a[i][j]-1);
                nine[(i-1)/3*3+(j-1)/3+1]|=1<<(a[i][j]-1);
            }else q[i]++;
        }
        for(int i=1;i<9;i++)for(int j=i+1;j<=9;j++)
        if(q[Hash[i]]>q[Hash[j]])swap(Hash[i],Hash[j]);
        while(q[Hash[k]]==0)k++;dfs(k);
    }return 0;
}
posted @ 2014-02-10 14:26  forever97  阅读(178)  评论(0编辑  收藏  举报