您的位置:首页 > 其它

深度优先搜索学习笔记

2018-02-21 23:02 295 查看

深度优先搜索

简单的说:深搜就是一搜到底:广搜就是一层一层的搜索:
(*^▽^*),这样说肯定是太抽象!

深度优先搜索

由霍普克洛夫特与罗伯特·塔扬提出,属于图论算法的一种,基本思路如下:
访问顶点;
从顶点出发,依次从没访问的点出发(要根据题意),对图进行深度优先遍历,直到都被访问或者不满足题意,
emm好吧~举一个栗子!
经典应用就是:走迷宫!

题目描述:

标题:方格分割6x6的方格,沿着格子的边线剪开成两部分。 要求这两部分的形状完全相同。如图:就是可行的分割法。 






试计算: 包括这3种分法在内,一共有多少种不同的分割方法。 注意:旋转对称的属于同一种分割法。请提交该整数,不要填写任何多余的内容或说明文字。

输入:

霍普克洛夫特罗伯特·塔扬输出:
请提交该整数,不要填写任何多余的内容或说明文字。

分析:如何剪出两个一样的图形?

以(3,3)为中心画出一条线直到边界,再将这条线中心对称即可。
结果的四分之一就是答案
上代码:
#include<iostream>
using namespace std;
int cns=0;
bool book[7][7]= {0};//用于记录是否走过。
int a[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
void dfs(int x,int y) {
if(x==0||x==6||y==0||y==6) {//停止条件
cns++;
return ;//不能有返回值!
} else {
book[3][3]=1;//标记最开始走过的位置
for(int i=0; i<=3; i++)//向四个方向走;
if(book[x+a[i][0]][y+a[i][1]]==1) continue;//走过了就继续向下走;
else {
book[x+a[i][0]][y+a[i][1]]=1;
book[6-x-a[i][0]][6-y-a[i][1]]=1;
dfs(x+a[i][0],y+a[i][1]);//尝试下一个点;
book[x+a[i][0]][y+a[i][1]]=0;//尝试结束取消这个点的标记
book[6-x-a[i][0]][6-y-a[i][1]]=0;//尝试结束取消这个点的标记
}
//			注意:尝试几个点就应该在尝试结束之后取消该点的标记;
}
}
int main() {
int x=3,y=3;
dfs(x,y);
cout<<cns/4;
return 0;
}
于是就能简单发现DFS有如下规律:
1. 是否走过;
2. 标记;
3. 出界条件;
4. 计数条件;
5. 是否需要重复初始化;
6. 试探走的路要取消标记;
7. 通过地图来进行走路;
8. 注意continue与return的使用,到达位置后return,也就是跳出,在没到达之前越界什么的只能continue因为这只是尝试失败而已。
9. 向新的方向走可以通过两种方法进行:第一种是将方向存入一个数组中,利用循环进行方向的移动;另一种是通过递归函数调用的时候改变调用的函数值:就像31点举的例子那样!
10. 深度搜索来求最短路径更新最值是在dfs函数里面比如:当到达终点之后个if(。。。)更新最值,return,注意,return空的意思是:返回空。。。要不你这么理解:相当于返回主函数的意思,return数值就是返回数值的意思;程序的语句是一句一句执行的于是就相当于你只是跳出了这个递归到头的函数(这个头指的是到达边界之后),然后就开始了接下来的递归函数调用,其实我感觉更新的过程时常伴有循环产生,递归调用就类似一种循环!有比较才有更新~想要反复比较就要循环!无论以哪种方式都是循环,循环结束了,那么答案也就得了出来!
11. 除了坐标之外,dfs函数中还有可能出现的函数参数:一般用于记录次数:实际上有参数就表明,这个参数需要随着递归的进行不断更新,也就是说重头到尾多要出现,恩,很容易就想到了通过设置临时变量进行最值的比较更新;
12.注意:关于算法:if(cur>=sum)//
return;
if(map[x][y]=='B') {
sum=cur;
return;
}
// if(map[x][y]=='B') {
// if(cur<sum) {
// sum=cur;
// return ;
// }
// }
注释掉的部分与没注释掉的部分有很大不同:只是掉的部分搜索的次数会多于没注释掉的部分:并且,使用注释掉部分的代码使用的前提是不存在死循环!即不会在迷宫内走圈圈。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: