POJ2676Sudoku

转载请注明出处:優YoU  http://user.qzone.qq.com/289065406/blog/1303713313

 

大致题意:

九宫格问题,也有人叫数独问题

把一个99列的网格,再细分为93*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。

 

0是待填位置,其他均为已填入的数字。

要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)

如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格

 

解题思路:

DFS试探,失败则回溯

 

用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝

bool row[10][10];    //row[i][x]  标记在第i行中数字x是否出现了

bool col[10][10];    //col[j][y]  标记在第j列中数字y是否出现了

bool grid[10][10];   //grid[k][x] 标记在第k3*3子格中数字z是否出现了

 

row col的标记比较好处理,关键是找出grid子网格的序号与 ij的关系

即要知道第ij列的数字是属于哪个子网格的

 

首先我们假设子网格的序号如下编排:


由于1<=ij<=9我们有: (其中“/”是C++中对整数的除法)


a= i/3 , b= j/3  ,根据九宫格的 行列 子网格 关系,我们有:


 

不难发现 3a+b=k

3*(i/3)+j/3=k

 

又我在程序中使用的数组下标为 1~9grid编号也为1~9

因此上面的关系式可变形为 3*((i-1)/3)+(j-1)/3+1=k

 

 

有了这个推导的关系式,问题的处理就变得非常简单了,直接DFS即可

 

 

  1 //Memory Time 
2 //184K 422MS
3
4 #include<iostream>
5 using namespace std;
6
7 int map[10][10]; //九宫格
8
9 bool row[10][10]; //row[i][x] 标记在第i行中数字x是否出现了
10 bool col[10][10]; //col[j][y] 标记在第j列中数字y是否出现了
11 bool grid[10][10]; //grid[k][x] 标记在第k个3*3子格中数字z是否出现了
12
13 //(这里说明的字母不代表下面程序中的变量)
14
15 bool DFS(int x,int y)
16 {
17 if(x==10)
18 return true;
19
20 bool flag=false;
21
22 if(map[x][y])
23 {
24 if(y==9)
25 flag=DFS(x+1,1);
26 else
27 flag=DFS(x,y+1);
28
29 if(flag) //回溯
30 return true;
31 else
32 return false;
33 }
34 else
35 {
36
37 int k=3*((x-1)/3)+(y-1)/3+1;
38
39 for(int i=1;i<=9;i++) //枚举数字1~9填空
40 if(!row[x][i] && !col[y][i] && !grid[k][i])
41 {
42 map[x][y]=i;
43
44 row[x][i]=true;
45 col[y][i]=true;
46 grid[k][i]=true;
47
48 if(y==9)
49 flag=DFS(x+1,1);
50 else
51 flag=DFS(x,y+1);
52
53 if(!flag) //回溯,继续枚举
54 {
55 map[x][y]=0;
56
57 row[x][i]=false;
58 col[y][i]=false;
59 grid[k][i]=false;
60 }
61 else
62 return true;
63 }
64 }
65 return false;
66 }
67
68 int main(int i,int j)
69 {
70 int test;
71 cin>>test;
72 while(test--)
73 {
74 /*Initial*/
75
76 memset(row,false,sizeof(row));
77 memset(col,false,sizeof(col));
78 memset(grid,false,sizeof(grid));
79
80 /*Input*/
81
82 char MAP[10][10];
83 for(i=1;i<=9;i++)
84 for(j=1;j<=9;j++)
85 {
86 cin>>MAP[i][j];
87 map[i][j]=MAP[i][j]-'0';
88
89 if(map[i][j])
90 {
91 int k=3*((i-1)/3)+(j-1)/3+1;
92 row[i][ map[i][j] ]=true;
93 col[j][ map[i][j] ]=true;
94 grid[k][ map[i][j] ]=true;
95 }
96 }
97
98 /*Fill the Sudoku*/
99
100 DFS(1,1);
101
102 for(i=1;i<=9;i++)
103 {
104 for(j=1;j<=9;j++)
105 cout<<map[i][j];
106 cout<<endl;
107 }
108 }
109 return 0;
110 }
原文地址:https://www.cnblogs.com/lyy289065406/p/2122549.html