初学算法----深度优先搜索

深度优先搜索大多可以看做在图上遍历和查找;

图的搜索有两种方式,一种是深度优先搜索(Depth-First-Search),另一种是广度优先搜索(Breadth-First-Search);

深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念。

(1).深度优先搜索的时间复杂度与空间复杂度大多取决于图;

图的表示方法:翁恺老师讲了:

    1.二维数组矩形表:  用二维数组G[i][j]存放图,G[i][j]能够表示i与j边界的情况(是否能通,其中的权,方向等)

    2.邻接表:每一个节点用一个一维数组表示边界情况;

    具体情况还是我学了数据结构再来吧;

(2)深度优先搜索的几种情况:

   1.是否能够找到正确路径:

伪代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
//判断是否能找到正确路径;
//函数的功能是判断是否能在现在的点上一直遍历找到路径
bool DFS (nowpoint)
{
if (nowpoint==终点)
{
return true;
}
if (nowpoint==旧点)
{
return false;
}
将nowpoint标记为旧点;
然后对nowpoint旁边的点进行遍历判断{
if (DFS (sidepoint))
{
return true;
}

}
如果对所有的旁边的点都进行了判断还没成功,
则退回到上一个点;
return false;
}
int main()
{
将所有点标记为未使用的点;
设置起点;
设置终点;
cout<<DFS (起点);
return 0;
}

    2.输出正确路径:

伪代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
int(数组的类型不唯一,具体看题目) array[10000];
int depth;
//函数的功能是判断是否能在现在的点上一直遍历找到路径,并记录路径;
bool DFS (nowpoint)
{
if (nowpoint==终点)
{
array[depth]==终点;
return true;
}
if (nowpoint==旧点)
{
return false;
}
标记nowpoint为旧点;
array[depth]=nowpoint;
depth++;
去让遍历nowpoint旁边其他点 {
if (DFS (sidepoint))
{
return true;
}

}
如果均无答案,则回退,弹出记录的点;
depth--;
return false;
}
int main()
{
//回退是没有代价的;
depth=0;
if ( DFS (起点) )
{
for (int i=0;i<=depth;i++)
{
printf ("%d",array[i]);
if (i!=depth)
{
printf ("->");
}
}
printf ("\n");
}
return 0;
}

当然这只能输出一条正确路径;

  3.遍历图上全部点:'

伪代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
//遍历图上的每一个点;
void DFS (nowpoint)
{
if (nowpoint==旧点)
{
return ;
}
标记nowpoint为旧点;
对旁边的点进行遍历{
DFS (sidepoint);
}
若无其他点,则回退;
return ;
}
int main()
{
将所有点标记为新点;
while (能够在图上找到新点)
{
DFS (新点);
}
return 0;

 //以下为实战:

棋盘问题:https://acs.jxnu.edu.cn/problem/NOIOPJCH0205323

这道题的输入如下:

输入:

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

输出:

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

样例输入:

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
对于这种的输入应如下写:
while (cin>>n>>k)
{
if (n==-1 && k==-1){break;}
for (int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)cin>>array[i][j];//最好用cin进行输入,因为cin会无视空格与回车,如果用scanf可能会将键盘缓冲区的奇怪东西输入;用getchar()我现在还把持不住;
}
}

代码如下:

版权声明:本文为CSDN博主「一枚研究生er」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40938077/article/details/80009760

这位大佬的代码我觉得很有递归感,而且简洁;

posted @ 2021-12-23 11:35  次林梦叶  阅读(236)  评论(0)    收藏  举报