【LibreOJ】#6298. 「CodePlus 2018 3 月赛」华尔兹 BFS

本文介绍了一种使用广度优先搜索(BFS)解决迷宫寻路问题的方法。通过给定n*m的网格,起点和终点位置,部分格子预设了前进方向,其余格子方向未知,算法的目标是在未知方向的格子中找到正确的方向,从而确保可以从起点成功到达终点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题意】给定n*m的网格,起点和终点位置,一些格指定下一步的方向,一些格任意。要求为方向任意的格确定方向,使起点可以走到终点。n,m<=50。

【算法】BFS

【题解】这道题最好用BFS,因为DFS容易陷入死路。

BFS过程中访问过的点标记vis,记录前驱后不用再访问,这是由于:

由于路径不可能走环,所以实际上可以忽略路径自身的影响,只保留能到达某个点的信息,最终到达终点(即访问过的点无需再访问)。

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1010;
const int fx[]={0,0,0,1,-1};
const int fy[]={0,1,-1,0,0};
int n,m,sx,sy,tx,ty,map[maxn][maxn],p[maxn][maxn];
bool v[maxn][maxn];
char s[maxn];
queue<int>Q;
bool c(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&!v[x][y];}
int main(){
    scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++){
            if(s[j]=='.')map[i][j]=0;
            if(s[j]=='d')map[i][j]=1;
            if(s[j]=='a')map[i][j]=2;
            if(s[j]=='s')map[i][j]=3;
            if(s[j]=='w')map[i][j]=4;
        }
    }
    Q.push(sx);Q.push(sy);v[sx][sy]=1;
    while(!Q.empty()){
        int x=Q.front();Q.pop();
        int y=Q.front();Q.pop();
        if(x==tx&&y==ty)break;
        if(map[x][y]>0){
            int X=x+fx[map[x][y]],Y=y+fy[map[x][y]];
            if(c(X,Y))Q.push(X),Q.push(Y),p[X][Y]=map[x][y],v[X][Y]=1;
        }
        else{
            for(int i=1;i<=4;i++){
                int X=x+fx[i],Y=y+fy[i];
                if(c(X,Y))Q.push(X),Q.push(Y),p[X][Y]=i,v[X][Y]=1;
            }
        }
    }
    int x=tx,y=ty;
    while(x!=sx||y!=sy){
        int X=x-fx[p[x][y]],Y=y-fy[p[x][y]];//
        map[X][Y]=p[x][y];
        x=X;y=Y;
    }
    printf("%d %d %d %d %d %d\n",n,m,sx,sy,tx,ty);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(map[i][j]==0||map[i][j]==1)printf("d");
            if(map[i][j]==2)printf("a");
            if(map[i][j]==3)printf("s");
            if(map[i][j]==4)printf("w");
        }
        puts("");
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/8511113.html

<think>好的,用户现在想了解迷宫问题的解决方案,特别是用BFS算法求最短路径和计算步数。我需要结合之前的讨论和提供的引用内容来组织回答。首先,用户之前的问题是关于排列组合生成不同数字的问题,现在转向迷宫问题,这可能是一个新的学习需求。用户提到的BFS算法、最短路径、步数计算以及障碍物处理,这些都是迷宫问题的关键点。根据引用内容,用户提供的资料中多次提到BFS在迷宫最短路径中的应用,比如引用[1]比较了BFS和DFS的适用场景,引用[3]、[4]、[5]详细描述了BFS解决迷宫问题的步骤。需要将这些信息整合起来,形成一个清晰的解决方案。 我需要先解释BFS的基本原理,为什么它适合找最短路径。然后,分步骤说明如何用BFS解决迷宫问题,包括队列的使用、访问标记、步数记录等。接着,提供一个具体的代码示例,最好是C++的,因为用户之前的例子是C++,但引用中的代码示例是Python,可能需要调整。不过用户没有明确语言要求,所以可以选通用性强的伪代码或Python,但考虑到引用[4]中的C++示例,可能更适合用C++。另外,要注意用户提到的输入格式,比如迷宫大小、起点终点坐标,障碍物的表示方法。在代码实现中需要处理这些输入,并确保正确性。同时,用户可能关心如何处理边界条件和障碍物,比如坐标是否从0开始或1开始,这需要明确说明。还需要强调BFS的空间复杂度问题,以及如何优化,比如双向BFS(引用[1]提到过),但用户当前的问题可能不需要太复杂的优化,保持基础实现即可。此外,要提到DFS的不足,比如不能保证最短路径,以突出BFS的优势。最后,生成相关问题,可能涉及其他算法比较、优化方法、应用场景等,这有助于用户进一步学习。现在需要确保回答结构清晰,分步骤讲解,代码正确,并正确引用提供的资料。同时,注意数学表达式的格式,比如步数计算中的层序遍历可能涉及层级数,可以用公式表示。例如,第n层的节点代表n步可达的位置,这样步数即为层数。</think>### 迷宫问题BFS解决方案 #### 问题建模 设迷宫为$m \times n$矩阵,其中: - 0/1表示空地(不同题目可能定义不同) - 障碍物标记为不可通行区域 - 起点$(x_1,y_1)$,终点$(x_2,y_2)$ 求从起点到终点的最短移动步数[^3][^5] #### BFS算法原理 广度优先搜索按层扩展,首次访问到终点时的路径即为最短路径[^1]。其时间复杂度为$O(mn)$,空间复杂度为$O(mn)$[^5] #### 实现步骤 1. **数据结构准备** ```cpp struct Node { int x, y, step; }; // 坐标步数 queue<Node> q; // 搜索队列 vector<vector<bool>> visited; // 访问标记 ``` 2. **方向向量定义** $$ \Delta x = \{-1,1,0,0\}, \Delta y = \{0,0,-1,1\} $$ // 上下左右四个方向[^4] 3. **核心算法流程 ```cpp q.push(start); visited[start.x][start.y] = true; while (!q.empty()) { Node cur = q.front(); q.pop(); if (到达终点) return cur.step; for (四个方向) { int nx = cur.x + dx[i]; int ny = cur.y + dy[i]; if (坐标合法 && 未访问 && 非障碍) { q.push({nx, ny, cur.step+1}); visited[nx][ny] = true; } } } return -1; // 无解 ``` #### 关键优化点 1. **层级步数记录**:每个节点保存当前步数,到达终点时直接返回 2. **剪枝策略**:先判断终点是否可达,避免无效搜索 3. **空间压缩**:使用位运算存储访问状态(当$m \times n \leq 64$时) #### 完整代码示例 ```cpp #include <iostream> #include <queue> using namespace std; struct Node { int x, y, step; }; int bfs(vector<vector<int>>& maze, Node start, Node end) { const int dx[] = {-1,1,0,0}, dy[] = {0,0,-1,1}; queue<Node> q; vector<vector<bool>> visited(maze.size(), vector<bool>(maze[0].size(), false)); q.push(start); visited[start.x][start.y] = true; while (!q.empty()) { Node cur = q.front(); q.pop(); if (cur.x == end.x && cur.y == end.y) return cur.step; for (int i = 0; i < 4; ++i) { int nx = cur.x + dx[i], ny = cur.y + dy[i]; if (nx >= 0 && nx < maze.size() && ny >= 0 && ny < maze[0].size() && !visited[nx][ny] && maze[nx][ny] == 1) { q.push({nx, ny, cur.step + 1}); visited[nx][ny] = true; } } } return -1; } int main() { int m, n; cin >> m >> n; vector<vector<int>> maze(m, vector<int>(n)); // 输入迷宫矩阵(1可通行,0障碍) for(int i=0; i<m; ++i) for(int j=0; j<n; ++j) cin >> maze[i][j]; Node start, end; cin >> start.x >> start.y >> end.x >> end.y; cout << bfs(maze, start, end); return 0; } ``` #### 复杂度分析 - 时间复杂度:$O(mn)$,每个节点访问一次 - 空间复杂度:$O(mn)$,队列和访问数组的存储开销[^1] #### 应用场景对比 | 算法 | 最短路径保证 | 空间消耗 | 适用场景 | |------|-------------|---------|---------| | BFS | 是 | 较高 | 迷宫导航、游戏AI[^2] | | DFS | 否 | 较低 | 路径枚举、地图生成[^1] | ### 相关问题 1. 如何处理带权迷宫的最短路径问题? 2. 双向BFS的实现原理优化效果? 3. A*算法如何结合启发式函数优化搜索? 4. 迷宫问题中如何处理斜向移动? 5. 如何记录并输出具体的最短路径?[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值