Sudoku is one of the metaphysical techniques. If you understand the essence of it, you will have the feeling of being immortal, laughing and laughing with joy.............................................................(audience:"We need't such a geomancer!You can get out!!")

  Oh,I'm sorry.Then let's getting down to business as quickly as possible.

    The meaning of the problem isn't hard for us to understand.And it is more friendly to those who have played sudoku.But don't worry if you didn't heard about this kind of game,for there's few skills of formal competition.What you have to do is to memorize its basic rules.

  OK.Now,let's think of the solution of this problem.You may want to enumerate all the alternative numbers in the blanks,then check if it's lawful.Good!it's the first algorithm we've thought of.But there's great room for progress.In fact,when people play sudoku,they will write down candidates in each blank.We can record which number we can use in one blank and try using it.To realize it,we can use state compression to save alternative numbers in each row,column and gong.After that,we can choose the blank which has the least candidates to have test-fill until all the blanks are filled.Don't forget to flash back after updating.

  Up to now,we are able to pass POJ2676,but there's still some distance from passing POJ3074.Think of how we search for the blank which has the least candidates and the use of lowbit.We can use an array to record the position of 1 in lowbit(x),and another one array to preprocess the number of 1 in each binary number.My code is below.

  After you get AC in these two sudokus,you can have a try in a harder promblem POJ3076.But you need more skillful way.Can you find it?

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int row[9],column[9],house[3][3],h[512],cnt[512];
 6 char a[9][9],c;
 7 bool flag;
 8 
 9 inline int getchoice(int x,int y){
10     return row[x]&column[y]&house[x/3+1][y/3+1];
11 }
12 
13 inline int lowbit(int x){
14     return x&-x;
15 }
16 
17 void dfs(int x,int y){
18     if(flag)    return;
19     if(x==10){
20         for(int i=0;i<=8;i++)
21             for(int j=0;j<=8;j++)   cout<<a[i][j];
22         cout<<endl;
23         flag=true;
24         return;
25     }
26     int hx=x/3+1,hy=y/3+1;//判断(x,y)在哪一宫
27     int choice=getchoice(x,y);
28     while(choice){
29         int num=lowbit(choice);
30         choice-=num;
31         int row0=row[x],column0=column[y],house0=house[hx][hy];
32         row[x]&=~num;column[y]&=~num;house[hx][hy]&=~num;
33         a[x][y]=h[num]+'1';
34         int minn=10,xx=10,yy;
35         for(int i=0;i<=8;i++)
36             for(int j=0;j<=8;j++){
37                 if(a[i][j]!='.') continue;
38                 int cal=cnt[getchoice(i,j)];
39                 if(cal<minn){
40                     xx=i;yy=j;
41                     minn=cal;
42                 }
43             }
44         dfs(xx,yy);
45         row[x]=row0;column[y]=column0;house[hx][hy]=house0;
46     }
47     a[x][y]='.';
48 }
49 
50 int main(){
51     for(int i=0;i<=8;i++) h[1<<i]=i;//预处理lowbit(x)后x中1的位置(即2^n中n的值)
52     for(int i=0;i<512;i++)
53         for (int j=i;j;j-=lowbit(j))
54             cnt[i]++;//题解中的好方法,预处理每一个二进制数中1的数量;
55     cin>>c;
56     while(c!='e'){
57         for(int i=0;i<=8;i++)
58             for(int j=0;j<=8;j++)
59                 row[i]=column[j]=house[i/3+1][j/3+1]=511;
60         a[0][0]=c;
61         for(int j=1;j<=8;j++)         scanf("%c",&a[0][j]);
62         for(int i=1;i<=8;i++)
63             for(int j=0;j<=8;j++)   scanf("%c",&a[i][j]);
64         for(int i=0;i<=8;i++)
65             for(int j=0;j<=8;j++)
66                 if(a[i][j]!='.'){
67                     int num=a[i][j]-'1';
68                     num=pow(2,num);
69                     row[i]&=~num;
70                     column[j]&=~num;
71                     house[i/3+1][j/3+1]&=~num;//预处理每行、每列、每宫可用的数字
72                 }
73         flag=false;
74         int minn=10,xx=10,yy;
75         for(int i=0;i<=8;i++)
76             for(int j=0;j<=8;j++){
77                 if(a[i][j]!='.') continue;
78                 int cal=cnt[getchoice(i,j)];
79                 if(cal<minn){
80                     xx=i;yy=j;
81                     minn=cal;
82                 }
83             }
84         dfs(xx,yy);
85         cin>>c;
86     }
87     return 0;
88 }
View Code

posted on 2019-03-11 10:46  酱骨a  阅读(314)  评论(0编辑  收藏  举报