当前位置: 代码迷 >> 综合 >> 搜索算法——DFS
  详细解决方案

搜索算法——DFS

热度:50   发布时间:2023-11-21 18:29:50.0

DFS

DFS,深度优先搜索,其过程可以简化为对每一个可能的分支路径深入到不能再深入的位置,而且每个结点只能访问以一次。

算法流程:

1.将初始结点入栈
2.访问栈顶元素
3.如果至少有一个与此点邻接且未被遍历的点,将其中一个入栈,否则将其出栈
4.重复2,3步,直到栈空

请观察并分析下图

在这里插入图片描述
如果以1作为根结点的话,入栈和出栈顺序是怎样的呢?
分析:先把1入栈,发现2,6未被遍历,我们将2入栈(我们可以人为规定先将序号较小的数入栈),发现3,4未遍历,将3入栈,发现5未遍历,将5入栈,发现4,7未遍历,将4入栈,此时4已经没有邻接点没有被遍历了,将4出栈,依次7入栈,6入栈,8入栈,8出栈,6出栈,9入栈,至此所有结点全部被遍历,依次将栈中元素出栈,9,7,5,3,2,1出栈,完成一次DFS。
c++模板如下
在这里插入图片描述
深度的定义为:当前搜索到的路径长度
eg:在这里插入图片描述
下面我们看两个例题
OpenJudge 1818:红与黑在这里插入图片描述
思路:
1.首先我们先找到起点
2.以起点为初始结点开始搜索
3.以上下左右的顺序寻找未被访问过的黑色结点
3.移动到下一个结点并打上标记,代表这个结点已经被访问过了
4.如果这个当前结点周围都被访问过了,返回上一结点
5.重复直至栈空
代码:

int m, n, counter = 1;
int mx[4] = {
     0,1,0,-1 };
int my[4] = {
     1,0,-1,0 };
bool nmap[30][30];
int a,b;
void dfs(int x, int y)
{
    for (int i = 0; i < 4; i++){
    if (nmap[x + mx[i]][y + my[i]] == true){
    x = x + mx[i]; y = y + my[i];nmap[x][y] = false;counter++;dfs(x, y);x = x - mx[i]; y = y - my[i];nmap[x][y]=true;}}
}

八皇后问题
在这里插入图片描述
思路:

代码:

#include<iostream>
#include<cstdio>
using namespace std;
int n;
int ans1;
int ans2[10010];
int vis1[10010];
int vis2[10010];
int vis3[10010];
void dfs(int now)
{
    if (now == n + 1){
    ans1++;if (ans1 <= 3){
    for (int i = 1; i <= n; i++)cout << ans2[i];cout << endl;}}for (int i = 1; i <= n; i++){
    if ((!vis1[i]) && (!vis2[n + (now - i)]) && (!vis3[n + (now + i - n - 1)])){
    vis1[i] = 1;//判断此列能否落子vis2[n + (now - i)] = 1;//判断左对角线是否可以落子,中间最长的对角线记作vis2[n],向左依次增大,向右依次减小,比如右上角的最短对角线为vis2[1],而左下的最短对角线为vis2[n+n-1]vis3[n + (now + i - n - 1)] = 1;//判断右对角线是否可以落子,和上面同理,vis3[1]代表左上对角线,vis3[n+n-1]代表右下对角线ans2[now] = i;dfs(now + 1);vis1[i] = 0;vis2[n + (now - i)] = 0;vis3[n + (now + i - n - 1)] = 0;}}
}
int main()
{
    cin >> n;dfs(1);return 0;
}