目录
文章目录
前言
一、什么是DFS?
二、什么是BFS?
三、题目演示(一个简单的题目,帮助理解)
前言
DFS和BFS在解决能够解决我们见到的很多图论问题,两者有很大的区别,但有些时候,两者又有相同的地方。比如都能通过搜索,来达到某种目的。接下来我们通过两道试题来简单的对DFS和BFS进行理解。
一、什么是DFS?
DFS就相当于是一个非常耿直,执着的人,当它走某条路的时候,只要不走到无路可走他就一直往前走,直至无路可走,然后就退回一步,去另一条路搜索。
二、什么是BFS?
BFS就相当于是一个平稳的人,它在搜索的时候是一层一层的搜索,直至搜索到我们想要的结果。
三、题目演示(一个简单的题目,帮助理解)
题目:
这一题用BFS和DFS都可以,但是用DFS搜索的,搜索的步骤比较多,有些过程会重复搜索,会导致时间复杂度高,会导致Time Limit Exceeded。
DFS题解:
差不多解这样的题都会使用同一个模板。只不过过程不太一样而已,过程如下。(解析都在题目上写着)
#include#include using namespace std; const int N=200; int a[N][N],book[N][N],n,m,mi=9999999; pair p[N]; void dfs(int x,int y,int k) { int next[4][2]={{0,1},{1,0},{-1,0},{0,-1}};//这一步相当于是移动 int kx,ky; if(x==n&&y==m)//当搜索到合适的位置的时候,输出并返回 { if(k "; //题目上不必写这一步,这一步是用来 //最短路时的过程是怎样的,使用pair记起来,当找到一个比原来步数小的就输出一下过程 cout<<"("< n||ky<=0||ky>m)//有一部分分支“很耿直”,直接撞南墙到出界 continue; if(book[kx][ky]==-1&&a[kx][ky]==0)//这一步在“一条路往南走的过程”没走过,而且这个位置不围墙 { p[k].first=kx; p[k].second=ky; book[kx][ky]=0; dfs(kx,ky,k+1); book[kx][ky]=-1;//当走完这一条路还要寻找其他可行的路,所以要让这个还原 } } return ; } int main() { memset(book,-1,sizeof(book)); cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j]; book[1][1]=0; dfs(1,1,0);//意思是从(1,1)位置走,现在是0步 cout<<"最短路"<
搜索次数太多导致了超时
BFS题解:
用BFS会很省时间,因为每一个位置只列举了一次,但是BFS比较浪费空间。
代码如下(示例):
//宽度优先遍历 #include#include using namespace std; const int N=110; struct PI { int x; int y; int s;//用来记录走第几步 int f;//来储存这一步的上一步是那一步 } a[N*N];//用数组来模拟队列。 int main() { int n,m,flag=1; cin>>n>>m; int book[n+1][m+1]; int nu[n+1][m+1]; memset(book,-1,sizeof(book));//将book数组内的值全部置为-1, //用来判断相对应的点是否走过。 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>nu[i][j];//输入对应的值(0表示可以走,1表示墙,走不通) int head=0,tail=0;//对队列初始化,头指针和尾指针都指向0 int next[4][2]={{0,1},{1,0},{-1,0},{0,-1}};//这一步相当于是移动 a[tail].x=1; a[tail].y=1; a[tail].f=0; a[tail++].s=0;//从(1,1)点出发(可以更改) while(tail>=head) { for(int i=0;i<4;i++){ int kx=a[head].x+next[i][0],ky=a[head].y+next[i][1]; if(kx<=0||kx>n||ky<=0||ky>m)//判断是否越界,越界之后不再进行以后的操作 continue; if(book[kx][ky]==-1&&nu[kx][ky]==0)//证明这一步没有走过,并且这个位置不是墙 { book[kx][ky]=0;//这一步走过了,以后都不需要再走了 a[tail].x=kx; a[tail].y=ky; a[tail].s=a[head].s+1;//接着你上一次走的走。因为这是队列,先把走某一步的处理完 //才能再继续处理下一步的。 a[tail++].f=head;//他的上一步为head(头指针的位置); //宽搜和深搜不同,不需要将book数组进行还原,每一个格子最多走一步 } if(kx==n&&ky==m) { flag=0;//在这里标记一下,如果找到结果,直接打断所有的循环 break;//搜索到了我们想要的点,直接输出即可 } } if(flag==0) break; //如果还没有找到,那就继续寻找,让头指针移动 head++; } cout< 小小的总结一下:
BFS和DFS各有好处,DFS(一般用栈来实现)比较耿直,其搜索的过程比较复杂,很多过程重复搜索,但其能找到我们想要的答案,空间复杂度低。而BFS(一般用队列来实现)就是一层一层的搜索,直至搜索到我们想要的结果就结束,其搜索没有重复的过程,其空间复杂度较高。两者没有谁好谁坏,只是二者适用于不同搜索类型的题。



