DFS 简单描述

基本思路

深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。 
当然,当人们刚刚掌握深度优先搜索的时候常常用它来走迷宫.事实上我们还有别的方法,那就是广度优先搜索(BFS).

简单来说

就是找跟(最深处)一直往下,如果走不通的话就回溯至上一层,然后再往下查找。
主体思路差不多,主要是输出和计数需要根据不同情况修改一下哦,注:dfs会把所有情况都走一遍,所以在走的过程中,考虑计数会很麻烦。

eg:八皇后问题:
在这里插入图片描述
题目描述:

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int hang[11], n=8;
int a[10][10] = { 0 };
int t = 1;
void print()
{
	printf("No. %d\n", t++);
	for (int i = 1; i <= 8; i++)
	{
		for (int j = 1; j <= 8; j++)
		{
			printf("%d ", a[j][i]);
		}
		printf("\n");
	}
}
bool judge(int num)
{
	for (int i = 1; i < num; i++)
		if (hang[num] == hang[i] || abs(hang[i] - hang[num]) == num - i)
			//判断列和对角线
			return 0;
	return 1;
}
 
void dfs(int num)
{
	if (num >= 9){
		print();
	}
	for (int i = 1; i <= 8; i++)
	{
		hang[num] = i;
		if (a[num][i]!=1&&judge(num))
		{
			a[num][i] = 1;
			dfs(num + 1);
			a[num][i] = 0;
		}
	}
}
 
int main()
{
		dfs(1);
	return 0;
}

主要考虑越界,还有就是判断函数,不能行相同,列相同,对角线相同,之后就是进行dfs即可。

eg:迷宫问题:

题目描述:

从s到t,.意味着可以走,*意味着不能走,如果能走,输出路径,如果不能走,输出no。
输入:

5 6

…S*
.*
.
.
.**.
.T…

输出:

…m*
.**mm
.
…*m
*.***m
.Tmmmm

#include <iostream>
#include <string>
using namespace std;
int n, m;
string maze[110];//或者设置一个二维数组进行循环输入,输出
bool vis[110][110];//看该位置是否被访问过,是标1,否0
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};//分别是不同方向
bool in(int x, int y) {
    return 0 <= x && x < n && 0 <= y && y < m;
}
bool dfs(int x, int y) {
    if(maze[x][y] == 'T'){//判断是否已经到达终点
        return true;
    }
    vis[x][y]=1;
    maze[x][y]='m';//走过标为m(地图上)
    for(int i=0;i<4;++i){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){
            if(dfs(tx,ty)){
                return true;
            }
        }
    }
    vis[x][y]=0;
    maze[x][y]='.';
    return false;
}
int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> maze[i];
    }
    int x, y;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (maze[i][j] == 'S') {
                x = i, y = j;
            }
        }
    }
    if (dfs(x, y)) {
        for (int i = 0; i < n; i++) {
            cout << maze[i] << endl;
        }
    } else {
        cout << "NO!" << endl;
    }
    return 0;
}

同理,如果需要统计有多少条路径,只需要在dfs函数中进行修改即可。

伪代码:

int sum = 0;
	sum += dfs(x - 1, y);//向左走
	sum += dfs(x + 1, y);//向右走
	sum += dfs(x, y - 1);//向上走
	sum += dfs(x, y + 1);//向下走
	vis[x][y] = 0;//该点还原为没有走过
	return sum;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫萧幕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值