深搜与广搜
DFS(深度优先搜索)
从起点出发,朝任一个可能的方向走,走过的点要做标记,一直向前走。若走不了了,就回退一步,从这一个状态走向没有走过的另一个方向。
之所以称为深度优先搜索,因为它是朝着一个方向一直走到底,以深度优先,然后回溯。
DFS一般用的是递归的方法。
迷宫问题
给一个迷宫,0表示道路,1表示墙壁,找出一条从左上角到右下角的最短路径
首先建立一个next[4][2]数组,表示下一步要走的方向,自定义方向的优先级,本题是从左上到右下,
那么,我可以按照下,右,上,左的顺序,则next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
遍历四个方向的代码为
for(int i=0;i<4;i++) tx=x+next[i][0];ty=y+next[i][1];//x,y为当前位置坐标,tx,ty为下一步要走的坐标
或者建立两个一维数组
int nx[4]={0,1,0,-1},ny={1,0,-1,0};
for(int i=0;i<4;i++)
{
int tx=x+nx[i],ty=y+ny[i];
}
还需要建立一个bool类型的vis[maxn][maxn]数组,来判断是否已经走过这条路
int nx[4]={0,1,0,-1},ny={1,0,-1,0}; void judge(int x,int y)//判断是否越界和是否已经走过 { return x>=0&&y>=0&&x<=n&&y<=m&&v[x][y]==0;//n为行数,m为列数 } void dfs(int x,int y,int step) { if(x==end1&&y==end2)//到达终点 { ans=min(ans,step); return; } v[x][y]=1;//标记为走过 for(int i=0;i<4;i++) { int tx=x+nx[i],ty=y+ny[i]; if(judge(tx,ty)) { dfs(tx,ty,step+1);//更新步数 } } v[x][y]=0;//回退时,清除标记, }
给出n个正整数a1,a2....an,和一个正整数k,问是否能从这n个数中选取若干个,使其和为k
int ans=0,a[N],b[N],sum=0,step=0;//ans表示有几种情况,step代表每种情况需要几个数使其和为k void dfs(int i,int sum,int step) { if(i==n+1)//当i等于n时,因为又递归了一次,所以要判断是否等于n+1,注意只有在n个数全部都枚举完了再判断sum是否等于k { if(sum==k) { ans++; b[ans]=step; } return; } dfs(i+1,sum+a[i],step+1);//加上a[i]的情况,数量加1 dfs(i+1,sum,step);//不加a[i]的情况 }
因为DFS采用递归的方法,所以很费时间,如果不剪枝的话,是很难AC的;
最简单的剪枝是sum>k时,直接返回
BFS(广度优先搜索),是一种利用队列(用队列来保存未访问的结点,先进先出)实现的搜索算法。简单来说,其搜索过程和 “湖面丢进一块石头激起层层涟漪” 、“树的层次遍历”类似。从源顶点s出发,依照层次结构,逐层访问其他结点。即访问到距离顶点s为k的所有节点之后,才会继续访问距离为k+1的其他结点。
bfs是按状态的层次进行扩展的,所以第一次访问到的终点节点所需步数,一定为最小步数
void bfs(初始状态)
{
新建队列q;
初始状态入队;
while(队列为空)
{
取出队首状态;出队;
if(到达目标状态) {跳出循环;}
for(遍历下一层状态)
{
if(该状态未被访问) 入队;
...
}
}
{
新建队列q;
初始状态入队;
while(队列为空)
{
取出队首状态;出队;
if(到达目标状态) {跳出循环;}
for(遍历下一层状态)
{
if(该状态未被访问) 入队;
...
}
}
struct node { int x,y,dis; node(int a,int b,int c):x(a),y(b),dis(c){} }start; int bfs(node start) { bool v[siz][siz]={0}; queue<node>q; q.push(start); v[start.x][start.y]=1; while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==endx&&now.y=endy) return now.dis; for(int i=0;i<4;i++) { int tx=now.x+dx[i],ty=now.y+dy[i]; if(can-move(tx,ty)) { v[tx][ty]=1; node newnode(tx,ty,dis+1); q.push(newnode); } } } return -1; }