DFS 解决数独问题
要求
输入 9X9 的数组,其中未知位置用 * 占用,用空格隔开(C++中的cin可以忽略空格)
DFS
这里总结一下 DFS 的算法步骤
- 访问起始节点:从图或树的起始节点开始遍历。
- 递归遍历邻接节点:对于当前节点的每个邻接节点,都进行深度优先搜索。
- 标记已访问节点:在遍历过程中,需要标记已经访问过的节点,以避免重复访问。
- 回溯:当无法继续深入时,需要回退到之前的节点,尝试其他路径。
这里给出代码
#include<bits/stdc++.h>
using namespace std;
char maze[10][10];
bool vx[10][10],vy[10][10],vv[10][10]; //下面有解释
bool f;
void dfs(int x,int y){
if(f){
return;
}
if(x==9){ //因为从0开始,当X = 9时已经完成了判断
f=true;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cout<<maze[i][j]<<" ";
}
cout<<endl;
}
return;
}
if(y==9){ //到这一行的末尾了,直接开始从下一行的第0个开始
dfs(x+1,0);
return;
}
if(maze[x][y]!='*'){
dfs(x,y+1);
return;
}
for(int i=0;i<9;i++){
if(!vx[x][i] && !vy[y][i] && !vv[x/3*3+y/3][i]){
maze[x][i]= i +'0';
vx[x][i]=true;
vy[y][i]=true;
vv[x / 3 * 3 + y / 3][i]=true;
dfs(x,y+1);
vx[x][i]=false; //因为要迭代,所以要重新设置回false
vy[y][i]=false;
vv[x / 3 * 3 + y / 3][i]=false;
maze[x][y]='*'; //归位
}
}
}
int main(){
for(int i==0;i<9;i++){
for(int j=0;j<9;j++){
cin>>maze[i][j];
}
}
//因为 maze 是 char类型,所以要转换为数字类型
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(maze[i][j]!='*'){
vx[i][maze[i][j]-'0']=true;
vy[j][maze[i][j]-'0']=true;
vv[x / 3 * 3 + y / 3][maze[i][j]-'0']=true;
}
}
}
dfs(0,0);
return 0;
}
代码解释
- 其中 vx 数组用来存储这一行里面的数字是否有使用。
- 类似 vy 数组用来存储并判别这一列的数字是否有占用或已经使用的情况。
- vv 数组用来判别该位数字在所对应的 3X3 的格子里对应的情况。
- 因为 dfs 大多是暴力搜索,不需要判别方格子里面累加和是否正确,只需要数字符合,就不会出错