一.定义
一条路走到尽头,往回一步,再一条路走到尽头,往回一步...直到达到终点。
步骤归纳:
访问起始节点v;
如果v的第一个邻接点没有访问过。深度遍历此邻接点;
如果当前的邻接点已经访问过了,再重新遍历v的第2个邻接点;
如果所有邻接点都已经访问过了,就返回上一个访问的顶点
二.应用--迷宫求解(在网格上的遍历)
题目描述
给出一个N*N的迷宫矩阵示意图,从起点[0,0]出发,寻找路径到达终点[N-1, N-1]。
输入
第一行输入t,表示有t个迷宫
第二行输入n,表示第一个迷宫有n行n列
第三行起,输入迷宫每一行的每个方格的状态,0表示可通过,1表示不可通过
输入n行
以此类推输入下一个迷宫
输出
逐个输出迷宫的路径
如果迷宫不存在路径,则输出no path并回车
如果迷宫存在路径,将路径中每个方格的x和y坐标输出,从起点到终点,每输出四个方格就换行,最终以单词END结尾,具体格式参考示范数据
tips:向右,向下、向左、向上逆时针探索路径。
输入样例
2
8
0 0 0 1 1 1 1 1
1 0 0 0 1 0 0 1
1 0 0 0 1 0 0 0
1 1 0 0 0 0 0 1
0 0 1 1 0 1 1 0
0 0 0 0 0 0 1 1
1 1 1 1 1 0 0 1
0 0 0 0 1 0 0 0
7
0 0 0 1 1 1 1
1 0 0 1 0 0 1
1 0 0 1 0 0 0
1 1 0 0 0 0 1
0 0 1 1 0 1 0
1 0 0 0 0 1 0
0 0 0 0 1 1 0
样例输出
[0,0]--[0,1]--[0,2]--[1,2]--
[1,3]--[2,3]--[3,3]--[3,4]--
[4,4]--[5,4]--[5,5]--[6,5]--
[6,6]--[7,6]--[7,7]--END
no path
参考代码
#include <iostream>
#include <stack>
using namespace std;
//每个点有两个属性:横坐标和纵坐标
class node
{
public:
int x, y;
node(int x1, int y1) { x = x1, y = y1; }
};
int main()
{
int t, n;
cin >> t;
while (t--)
{
stack<node>path, path1; //path作为临时变量,path1输出最后的路径
int a[300][300];
cin >> n;
//输入邻接矩阵
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cin >> a[i][j];
}
//如果迷宫的初始点不能走,则没有路径可走
if (a[0][0] == 1)
{
cout << "no path" << endl;
continue;
}
//初始点可以走
else
{
//将可以走的点信息存储起来
path.push(node(0, 0));
a[0][0] = 1;//将走过的点标记为"1"
int nowx = 0, nowy = 0;//初始化现在的坐标为初始点的坐标
while (1)
{
//注意迷宫的坐标范围是0-n-1,则要判断横纵坐标改变后是否超出迷宫边界
if (a[nowx][nowy + 1] == 0 && nowy + 1 < n)//向右走
{
path.push(node(nowx, nowy + 1));
a[nowx][nowy + 1] = 1;
nowy += 1;
}
else if (a[nowx + 1][nowy] == 0 && nowx + 1 < n)//向下走
{
path.push(node(nowx + 1, nowy));
a[nowx + 1][nowy] = 1;
nowx += 1;
}
else if (a[nowx][nowy - 1] == 0 && nowy - 1 >= 0)//向左走
{
path.push(node(nowx, nowy - 1));
a[nowx][nowy - 1] = 1;
nowy -= 1;
}
else if (a[nowx - 1][nowy] == 0 && nowx - 1 >= 0)//向上走
{
path.push(node(nowx - 1, nowy));
a[nowx - 1][nowy] = 1;
nowx -= 1;
}
//如果一条路走到了尽头,就往回走一步,体现在"pop"出当前结点
else
{
nowx = path.top().x;
nowy = path.top().y;
if (!((a[nowx][nowy + 1] == 0 && nowy + 1 < n) ||
(a[nowx + 1][nowy] == 0 && nowx + 1 < n) ||
(a[nowx][nowy - 1] == 0 && nowy - 1 >= 0) ||
(a[nowx - 1][nowy] == 0 && nowx - 1 >= 0)))
{
path.pop();
}
}
//到达终点就跳出循环,输出路径
if (path.empty() || (nowx == n - 1 && nowy == n - 1)) break;
}
//路径为空,也就是在初始点没有邻接点可以走
if (path.empty())
{
cout << "no path" << endl;
}
//存在路径就输出路径
else
{
while (!path.empty()) { path1.push(path.top()); path.pop(); }
int i = 0; //以下是输出路径的代码
while (!path1.empty())
{
node cpos = path1.top();
if ((++i) % 4 == 0)
cout << '[' << cpos.x << ',' << cpos.y << ']' << "--" << endl;
else
cout << '[' << cpos.x << ',' << cpos.y << ']' << "--";
path1.pop();
}
cout << "END" << endl;
}
}
}
return 0;
}
三.应用--在图上的遍历
题目描述
给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始
注意:图n个顶点编号从0到n-1
输入
第一行输入t,表示有t个测试实例
第二行输入n,表示第1个图有n个结点
第三行起,每行输入邻接矩阵的一行,以此类推输入n行
第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开
以此类推输入下一个示例
输出
每行输出一个图的深度优先搜索结果,结点编号之间用空格隔开
输入样例
2
4
0 0 1 1
0 0 1 1
1 1 0 1
1 1 1 0
5
0 0 0 1 1
0 0 1 0 0
0 1 0 1 1
1 0 1 0 0
1 0 1 0 0
样例输出
0 2 1 3
0 3 2 1 4
参考代码
#include<iostream>
using namespace std;
const int maxn = 50;//假定图最多包含50个顶点
int g[maxn][maxn];//图的邻接矩阵
int visit[maxn];//访问标志数组,标识每个结点是否已经访问过,1表示访问过,0表示未访问过
int vnum;//结点数量
void DFS(int now)//now表示当前结点
{
cout << now << " ";
visit[now] = 1;
int* a = new int[vnum];//存放与当前结点相连(有边)的结点编号
for (int i = 0; i < vnum; i++)
{
a[i] = -1;
}
int k = 0;
for (int i = 0; i < vnum; i++)
{
if (g[now][i])//编号为i的结点与当前结点相连(有边)
{
a[k++] = i;//存放到数组里
}
}
int i = 0;
for (int w = a[i]; w != -1; w = a[++i])
{
if (!visit[w])
{
DFS(w);
}
}
delete[]a;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> vnum;
for (int i = 0; i < vnum; i++)
visit[i] = 0;
//输入邻接矩阵,1表示结点之间相连,0表示结点之间没有相连
for (int i = 0; i < vnum; i++)
{
for (int j = 0; j < vnum; j++)
cin >> g[i][j];
}
for (int v = 0;v< vnum;v++)
{
//若该顶点未访问,就调用DFS函数进行深度优先搜索
if (!visit[v])
{
DFS(v);
}
}
cout << endl;
}
return 0;
}