1.前言
本文将以经典的八皇后问题来解析dfs的主要思想。
2.题目
题目出处:活动 - AcWing
3.思路讲解
dfs的思想暗含树的历遍,主要步骤为:
判断是否搜索完毕---历遍寻找符合条件的元素---递归进入下一层搜索---还原现场
我们可以先分析这个问题,发现皇后在每一行只能有一个,并且对角线,反对角线,每一排,每一列都只有一个皇后。
那么我们就可以从底层出发,遍历一排中的每一个元素,然后深入搜索下一排符合条件的元素,搜索到最后时,即是符合条件的第一个答案,回溯到第一排的下一个元素进行搜索。
由于dfs的灵魂是递归,所以递归的知识一定要掌握清楚。
4.代码实现
参照以下网格来理解代码:
该方法符合dfs的一般做法,当然算法是死的,人是活的,依照不同的题目,dfs的参数,形式等多种多样,不敢一板子把代码论死。要参照思想,具体情况具体分析,dfs最重要的便是顺序!!!
4.1 法1
#include <iostream>
using namespace std;
const int N = 20;
//定义图(网格)
char path[N][N];
//col记录每一列的皇后数,确保只有1个
//dg记录正对角线的皇后数,确保只有1个
//udg记录反对角线的皇后数,确保只有1个
bool col[N],dg[N],udg[N];
//网格数n
int n;
void dfs(int u)
{
//搜索完毕,并且符合要求时打印
if(u==n)
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cout<<path[i][j];
}
cout<<endl;
}
cout<<endl;
return;
}
//y代表y轴上的点
for(int y = 0; y < n; y++)
{
//如果一列里面没有元素,对角线上没有元素,那么放入皇后Q;
if(!col[y]&&!dg[y+u]&&!udg[y-u+n])
{
path[u][y]='Q';
col[y]=dg[y+u]=udg[y-u+n]=true;
//皇后数+1,进入下一层搜索
dfs(u+1);
//回溯到原始状态
col[y]=dg[y+u]=udg[y-u+n]=false;
path[u][y]='.';
}
}
}
int main()
{
cin>>n;
//先初始化网格,再由dfs确定皇后位置
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
path[i][j]='.';
}
}
//从第0层开始(初始皇后数为0)
dfs(0);
return 0;
}
这里解释一下对角线的判定:
由直线方程y=(±)x+b;
我们想要一条对角线上的皇后只有一个,而一条直线上,截距是一样的,b = y ± x ;
但是由于数组的下标没有负数, y - x 有可能是负数,所以加上n,映射成正数!
如果(u)dg[ b ] 为真,那么该直线上已经有一个皇后。
4.2 法2
#include <iostream>
using namespace std;
const int N = 20;
char path[N][N];
//判断行,列,对角线
bool row[N],col[N],dg[N],udg[N];
int n;
void dfs(int x,int y,int s)
{
//初始化条件
if(y == n)
{
x++;
y = 0;
}
if(x == n)
{
//搜素完毕,并且符合要求的条件
if(s==n)
{
for(int i = 0; i < n; i++)
{
puts(path[i]);
}
puts(" ");
}
return;
}
//初始化网格
path[x][y]='.';
dfs(x,y+1,s);
//思路同法1
if(!row[y]&&!col[x]&&!dg[x+y]&&!udg[y-x+n])
{
row[y]=col[x]=dg[x+y]=udg[y-x+n]=true;
path[x][y]='Q';
dfs(x,y+1,s+1);
row[y]=col[x]=dg[x+y]=udg[y-x+n]=false;
path[x][y]='.';
}
}
int main()
{
cin>>n;
dfs(0,0,0);
return 0;
}
但是法2在效率上远不如法1,因为在初始化回溯时进行搜索,浪费了很多不必要的搜索,只有当x,y回溯到0时才真正起到作用。
举此法是为了说明dfs的灵活性。
5.结语
作为图论的必备入门技巧,要把握dfs的思想,并且熟练运用。
其实dfs更像一种循环,在if条件下找到不同层数的答案,完成搜索后继续下一个搜索,在不影响原来的数据的情况下输出答案。
后续会更新bfs的有关内容。