基本思路
深度优先遍历图的方法是,从图中某顶点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;