DFS之数独

18 阅读2分钟

DFS 解决数独问题

要求

输入 9X9 的数组,其中未知位置用 * 占用,用空格隔开(C++中的cin可以忽略空格)

DFS

这里总结一下 DFS 的算法步骤

  1. 访问起始节点:从图或树的起始节点开始遍历。
  2. 递归遍历邻接节点:对于当前节点的每个邻接节点,都进行深度优先搜索。
  3. 标记已访问节点:在遍历过程中,需要标记已经访问过的节点,以避免重复访问。
  4. 回溯:当无法继续深入时,需要回退到之前的节点,尝试其他路径。

这里给出代码

#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 大多是暴力搜索,不需要判别方格子里面累加和是否正确,只需要数字符合,就不会出错