POJ3074 Sudoku

Sudoku
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10745   Accepted: 3850

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

. 2 7 3 8 . . 1 .
. 1 . . . 6 7 3 5
. . . . . . . 2 9
3 . 5 6 9 2 . 8 .
. . . . . . . . .
. 6 . 1 7 4 5 . 3
6 4 . . . . . . .
9 5 1 8 . . . 7 .
. 8 . . 6 5 3 4 .

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936


题目大意:
  数独求解


分析:
    这道题的数据强于POJ2676
  所以一般的DFS是TLE的
  但本蒟蒻又不会dancing links
  所以学习了一种类似于状态压缩的方法来判断每一行,每一列,每一个九宫格的数字使用情况
  我们可以对于每一行,每一列,每一个九宫格都用一个9位二进制数来存储,再使用bitset来将可以使用的数字取出
  (对于每一个空位优先搜索可用数字少的,可以加快速度
  最后DFS


代码如下
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
 5 int heng[10];
 6 int shu[10];
 7 int ge[10];
 8 int cnt[512],num[512],tot;
 9 char ss[10][10];
10 char s[100];
11 int ID(int x,int y)
12 {
13     return ((x/3)*3)+(y/3);
14 }
15 void visit(int x,int y,int z)
16 {
17     heng[x]^=1<<z;
18     shu[y]^=1<<z;
19     ge[ID(x,y)]^=1<<z;
20 }
21 bool dfs(int now)
22 {
23     if(now==0)return true;
24     int temp=10,x,y;
25     for(int i=0;i<9;i++)
26     {
27         for(int j=0;j<9;j++)
28         {
29             if(ss[i][j]!='.')continue;
30             int v=heng[i]&shu[j]&ge[ID(i,j)];
31             if(!v)return false;
32             if(cnt[v]<temp)
33             {
34                 temp=cnt[v];
35                 x=i,y=j;
36             }
37         }
38     }//可用数字最少的空位
39     int v=heng[x]&shu[y]&ge[ID(x,y)];
40     for( ;v ;v-=v&-v)
41     {
42         int z=num[v&-v];
43         ss[x][y]='1'+z;
44         visit(x,y,z);
45         if(dfs(now-1))return true;
46         visit(x,y,z);
47         ss[x][y]='.';
48     }//取出数字再DFS
49     return false;
50 }
51 int main()
52 {
53     for(int i=0;i<1<<9;i++)
54     {
55         for(int j=i;j;j-=j&-j)cnt[i]++;
56     }
57     for(int i=0;i<9;i++)
58     {
59         num[1<<i]=i;
60     }
61     while(scanf("%s",s)&&s[0]!='e')
62     {
63         for(int i=0;i<9;i++)
64         {
65             for(int j=0;j<9;j++)
66             {
67                 ss[i][j]=s[i*9+j];
68             }
69         }
70         for(int i=0;i<9;i++)
71         {
72             heng[i]=shu[i]=ge[i]=(1<<9)-1;
73         }
74         tot=0;
75         for(int i=0;i<9;i++)
76         {
77             for(int j=0;j<9;j++)
78             {
79                 if(ss[i][j]!='.')visit(i,j,ss[i][j]-'1');
80                 else tot++;
81             }
82         }
83         dfs(tot);
84         for(int i=0;i<9;i++)
85         {
86             for(int j=0;j<9;j++)
87             {
88                 s[i*9+j]=ss[i][j];
89             }
90         }
91         printf("%s
",s);
92     }
93     return 0;
94 }
原文地址:https://www.cnblogs.com/xxjnoi/p/8619129.html