自学算法

第二周_自学算法

1. DFS 和 BFS

迷宫问题:

题意:

​ 找到从起点到终点的最短路径长度。

思路1:

深度优先搜索 (DFS)

从起始位置出发, 按照顺时针方向沿着一个方向向下试探, 找到终点, 若还有其他可到达终点的路径就回溯, 以此类推找到所有可到达终点的路径, 过程中记录能到达终点的较短路径, 最后输出最短路径。

注: 每个位置都有上, 下, 左, 右四个方向可以走, 我们规定按顺时针方向右, 下, 左, 上进行探索

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 50;  // 迷宫行和列的最大值

int n, m;  // n 行, m列
int start_x, start_y, end_x, end_y;  // 起始位置和终点坐标
int arr[N + 10][N + 10];  // 要输入的迷宫图, 用 1 表示是空地, 用 2 表示障碍物
int v[N + 10][N + 10];  // 标记, 1 表示已标记不能走, 0 表示是空地可以走
int min1 = INT_MAX;  // 最短路径
int d_x[4] = {0, 1, 0, -1}, 
	d_y[4] = {1, 0, -1, 0};  // 按右, 下, 左, 上探索

void dfs(int x, int y, int step)  // 每走一个单元格 step 加 1
{
    // 找到终点的情况
    if (x == end_x && y == end_y)
    {
        if (step < min1) min1 = step;
        return;	// 回溯
    }
    
    // 探索
    for (int k = 0; k < 4; k++)
    {
        int sx = x + d_x[k];
        int sy = y + d_y[k];
        // 判断能不能走
        if (arr[sx][sy] == 1 && v[sx][sy] == 0)
        {
            v[sx][sy] = 1;  // 能走就标记
            dfs(sx, sy, step + 1);  // 往前探索
            v[sx][sy] = 0;  // 回溯时收回标记
        }
    }
    
    return;
}

int main(void)
{
    cin >> n >> m;
    
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &arr[i][j]);
    
    cin >> start_x >> start_y;
    cin >> end_x >> end_y;
    
    dfs(start_x, start_y, 0);
    
    cout << min1;
    
    return 0;
}

思路2:

广度优先搜索 (BFS)

  1. 将起点入队

  2. 若队首结点能扩展, 则将能扩展的点入队; 若队首不能再扩展, 则将队首结点出队

  3. 重复第二步, 直到到达终点或队为空时结束

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 50;

int n, m;  // n 行, m列
int start_x, start_y, end_x, end_y;  // 起始位置和终点坐标
int arr[N + 10][N + 10];  // 要输入的迷宫图, 用 1 表示是空地, 用 2 表示障碍物
int v[N + 10][N + 10];  // 标记, 1 表示已标记不能走, 0 表示是空地可以走
int d_x[4] = {0, 1, 0, -1}, 
	d_y[4] = {1, 0, -1, 0};	// 按右, 下, 左, 上探索

// 结点结构体
struct point
{
    int x;
    int y;
    int step;
};

queue<point> p;	// 申请队列

void bfs(int start_x, int start_y)
{
    // 起点入队
    point start;
    start.x = start_x;
    start.y = start_y;
    start.step = 0;
   	p.push(start);
    v[start_x][start_y] = 1;
    
    while (!p.empty())
    {
        int x = p.front().x;
        int y = p.front().y;
        
        // 到达终点情况
        if (x == end_x && y == end_y)
        {
            cout << p.front().step;
            break;
        }
        
        // 探索
        for (int k = 0; k < 4; k++)
        {
            int sx = x + d_x[k];
            int sy = y + d_y[k];
            if (arr[sx][sy] == 1 && v[sx][sy] == 0)
            {
                point temp;
                temp.x = sx;
                temp.y = sy;
                temp.step = p.front().step + 1;
                p.push(temp);
                v[sx][sy] = 1;
            }
        }
        p.pop();  // 不能或扩展完后就出队
    }
}

int main(void)
{
    cin >> n >> m;
    
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &arr[i][j]);
    
    cin >> start_x >> start_y;
    cin >> end_x >> end_y;
    
    bfs(start_x, start_y);
    
    return 0;
}

输入:

5 4
1 1 2 1
1 1 1 1
1 1 2 1
1 2 1 1
1 1 1 1
1 1
4 3

输出:

7

/*
DFS 和 BFS 这两个算法是我在 B 站上的 up: 麦克老师讲算法那里学的, 老师讲的很细。
链接: https://www.bilibili.com/video/BV1bK4y1C7W2/?spm_id_from=333.337.search-card.all.click&vd_source=608bcc17ec645dcf71581245d5ae3339
*/

posted @ 2023-01-09 23:26  aili_code  阅读(98)  评论(0)    收藏  举报