深搜&&广搜初步详解

DFS&&BFS初步

深搜原理

深搜,顾名思义,是深入其中、直取结果的一种搜索方法。

深搜优缺点

  • 优点

1、能找出所有解决方案
2、优先搜索一棵子树,然后是另一棵,所以和广搜对比,有着内存需要相对较少的优点

  • 缺点

1、要多次遍历,搜索所有可能路径,标识做了之后还要取消。
2、在深度很大的情况下效率不高

  • 深搜模板

    void DFS() //N代表目前DFS的深度
    {
    	if(找到解) //进行相应的操作
    	{return;
    	}
    	for(inti=0;i<4;i++) //枚举四个方向
    	{
        	DFS(N+1); //进入下层递归
    	}
    }
    
    

迷宫

题目描述

给定一个 N × M N \times M N×M 方格的迷宫,迷宫里有 T T T 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N , M , T N,M,T N,M,T,分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 S X , S Y , F X , F Y SX,SY,FX,FY SX,SY,FX,FY S X , S Y SX,SY SX,SY 代表起点坐标, F X , F Y FX,FY FX,FY 代表终点坐标。

接下来 T T T 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

样例 #1

样例输入 #1

2 2 1
1 1 2 2
1 2

样例输出 #1

1

提示

对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 5 1 \le N,M \le 5 1N,M5 1 ≤ T ≤ 10 1 \le T \le 10 1T10 1 ≤ S X , F X ≤ n 1 \le SX,FX \le n 1SX,FXn 1 ≤ S Y , F Y ≤ m 1 \le SY,FY \le m 1SY,FYm

#include <bits/stdc++.h>
using namespace std;
int N, M, T;
int ans;
int sx, sy, fx, fy, dx, dy;
int a[11][11], book[11][11];
void dfs(int x, int y)
{
    int next[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; //可以直接用二维数组表示路径
    int tx, ty, k;
    if (x == fx && y == fy) //如果找到了终点,就停止深搜
    {
        ans++;
        return;
    }
    for (int k = 0; k <= 3; k++)
    {
        tx = x + next[k][0]; //深搜模板
        ty = y + next[k][1];
        if (tx < 1 || tx > N || ty < 1 || ty > M) //下一个点是否出界
            continue;
        if (a[tx][ty] == 0 && book[tx][ty] == 0) //如果该点不是障碍且没有走过
        {
            book[tx][ty] = 1; //则标记
            dfs(tx, ty);      //继续深搜
            book[tx][ty] = 0; //一路深搜到尽头后返回来取消标记,相当于没走过,然后去搜别的路
        }
    }
    return;
}
int main()
{
    cin >> N >> M >> T;
    cin >> sx >> sy >> fx >> fy;
    book[sx][sy] = 1; //标记起始点为走过
    for (int i = 1; i <= T; i++)
    {
        cin >> dx >> dy;
        a[dx][dy] = 1;
    }
    dfs(sx, sy);
    cout << ans;
}

广搜原理

广搜,顾名思义,是多管齐下、广撒网的一种搜索方法

广搜优缺点

  • 优点

1、对于解决最短或最少问题特别有效,而且寻找深度小
2、每个结点只访问一遍,结点总是以最短路径被访问,所以第二次路径确定不会比第一次短

  • 缺点

1、内存耗费量大(需要开大量的数组单元用来存储状态)

广搜模板

void BFS() 
{ 	… …//初始化起点入队 
	while(!q.empty()) //判断队是否为空
	{	… …//获取队首元素
		if(...){… …}//判断是否是终点
		for(int i=0;i<4;i++)//四个方向
		{ 
			k.x=p.x+dir[i][0];
	    	k.y=p.y+dir[i][1];
			//向各个方向走一步
	     	if(judge())//判断能不能走
			{
		    	… …//各种处理 
    		    vis[k.x][k.y]=1; //标记 	
	        	q.push(k); //入队
			}
		}
	}
}

马的遍历

题目描述

有一个 n × m n \times m n×m 的棋盘,在某个点 ( x , y ) (x, y) (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n , m , x , y n, m, x, y n,m,x,y

输出格式

一个 n × m n \times m n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 − 1 -1 1)。

样例 #1

样例输入 #1

3 3 1 1

样例输出 #1

0    3    2    
3    -1   1    
2    1    4

提示

数据规模与约定

对于全部的测试点,保证 1 ≤ x ≤ n ≤ 400 1 \leq x \leq n \leq 400 1xn400 1 ≤ y ≤ m ≤ 400 1 \leq y \leq m \leq 400 1ym400

#include <bits/stdc++.h>
using namespace std;
bool book[401][401]; //标记是否走过
int n, m;
int ans[401][401]; //用来储存答案
int x_next[8] = {2, 1, 1, 2, -1, -2, -2, -1};
int y_next[8] = {1, 2, -2, -1, 2, 1, -1, -2};
struct queue
{
    int x, y;
} que[40001]; //构建bfs的队列
int check(int x, int y)
{
    if (x < 1 || x > n || y < 1 || y > m)
        return 0;
    return 1;
} //判断是否越界
void bfs(int x, int y)
{
    int head = 0, tail = 1; //队列指针一头一尾
    int sum = 0;            //步数清零
    que[1].x = x;
    que[1].y = y;
    //初始点入队
    book[x][y] = 1;
    //标记初始点
    ans[x][y] = 0;
    while (head < tail) //搜完了就退出
    {
        head++; //首项出队
        sum = ans[que[head].x][que[head].y] + 1;
        //标记步数
        for (int i = 0; i < 8; i++)
        {
            int tx = que[head].x + x_next[i];
            int ty = que[head].y + y_next[i];
            if (check(tx, ty) && !book[tx][ty]) //如果该点不在界外,而且未走过
            {
                tail++;
                que[tail].x = tx; //将该点加入队列尾部
                que[tail].y = ty;
                book[tx][ty] = 1;
                ans[que[tail].x][que[tail].y] = sum; //存储答案
            }
        }
    }
}
int main()
{
    int x, y;
    cin >> n >> m >> x >> y;
    memset(ans, -1, sizeof(ans));
    bfs(x, y);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cout << ans[i][j] << "    ";
        }
        cout << endl;
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值