题目描述:
http://poj.org/problem?id=2676
中文大意:
数独是一项非常简单的任务。
9x9 的正方形表可以被划分为 9 个较小的 3x3 的正方形。
尝试在空白单元格中填入数字 1-9,使得每一行、每一列和每个 3x3 子正方形中都能显示 1-9 的所有数字。
思路:
共有 81 个单元格,从第 0 个开始进行填写。
填写原则是:当前单元格空白,填写的数字是同行、同列以及 3x3 范围内均未出现过的。
选择一个可填写的数字,填写在该位置,就可以去填写下一位置,直至所有单元格填写完毕。
回溯回来后,继续尝试剩余可填写数字。
代码:
#include<iostream>
using namespace std;
int maps[9][9];//9x9 表格
//确定可填元素
void check(int row, int col, bool visited[]){
//检查同列元素
for(int i=0;i<9;i++){
visited[maps[i][col]] = true;
}
//检查同行元素
for(int j=0;j<9;j++){
visited[maps[row][j]] = true;
}
//检查3x3区域元素
col = col / 3 * 3;
row = row / 3 * 3;
for(int i=row;i<row+3;i++){
for(int j=col;j<col+3;j++){
visited[maps[i][j]] = true;
}
}
}
bool have_result;//是否有解
void dfs(int index){
//已经有了一组解,结束搜索
if(have_result){
return;
}
//表格填涂完毕
if(index == 81){
have_result = true;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
printf("%d", maps[i][j]);
}
printf("
");
}
return;
}
int x = index % 9;
int y = index / 9;
//当前位置存在数字,则填涂下一位置
if(maps[y][x] != 0){
dfs(index+1);
}
else{
//确定可以填写哪些数字
bool visited[10] = {false};
check(y, x, visited);
for(int i=1;i<=9;i++){
if(!visited[i]){
maps[y][x] = i;
dfs(index+1);
//记得恢复公共资源 maps,因为一次深搜后,maps已经被修改
//回溯到前状态后,需要使用原来的 maps
maps[y][x] = 0;
}
}
}
}
int main(){
int n;
scanf("%d", &n);
while(n--){
char temp[9];
for(int i=0;i<9;i++){
scanf("%s", temp);
for(int j=0;j<9;j++){
maps[i][j] = temp[j] - '0';
}
}
have_result = false;
dfs(0);
}
}