第十届蓝桥杯省赛C/C++B组第E题 迷宫(BFS基础)

迷宫,广搜入门


【问题描述】
下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可
以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这
个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫,
一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。

对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式,
其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。
请注意在字典序中D<L<R<U。(如果你把以下文字复制到文本文件中,请务
必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 maze.txt,
内容与下面的文本相同)

【输入】

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

答案
186 步

DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR

路径表示

迷宫搜索结果
思路
纯粹的一道广度优先搜索的题目。

需要记录路径,并且要求是字典序列最小。

因此,在循环遍历四个方向的时候需要按照字典序列从小到大的顺序来搜索,这样子找到的第一个结果就是最终答案 (这道水题只有一条路径)。

广搜不同于深搜,它是每一条可能的路线同时进行搜索。因此每次向外扩展一层,是让所有可能的路线的所走步数同时加1。最后有的路线会走入死胡同,随之被抛弃。

当其中一条路线达到目的地时,这条路线必然是最短的,之后即使又有一些路线可以到达目的地,但花费的步数只能是大于等于第一条到达的路线(可能是和第一条到达的路线在同一层循环时到达目的地,或者是在落后几层搜索中到达目的地)

编程细节

有的时候吧, 很久没用这种知识点,很多细节容易忘记。这里把一些编程时容易忘记的地方提一下。

  1. 明确所需要搜索的对象或各节点具有什么属性。比如,坐标、到达时花费的步数、到达时所经过的路径。

  2. 广度搜索主要所使用的工具是队列,有的特殊情况还需要使用优先队列。先将起点加入到队列当中,并且标记,起点为已经过的点。然后,按照一定的搜索方式,循环将队列的第一个元素取出来,然后在队列中将其删除,表示对该点搜索完了。对取出来的点,先判断是否为最终答案,如果不是的话,由该点搜索出来其他的(四个)新点加入到队列的尾部,作为接下来判断的对象。

  3. 一般做这类题,需要建立一个二维数组来存地图;
    另外一个二维数组作为标记已经搜索完的点的位置;
    一个方向数组,作为搜索时坐标的转移;
    一个结构体,封装每一步搜索到的节点所记录的信息,可以是坐标,路劲,步数;
    一个结构体类型的队列,或者优先队列。

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <string>
using namespace std;

const int H = 33, L = 53;
const int N = H*L;

char a[H][L];
bool vis[H][L];
int dir1[4][2] = { {1 , 0}, {0 , -1}, {0 , 1}, {-1 , 0} };
char dir2[4] = { 'D', 'L', 'R', 'U' };

struct note
{
    int x, y;     //坐标
    char ans[N];  //字符串答案,表示搜索过的路径,这里使用c++中的string类型更加方便
    int step;     //步数
    note(int a, int b, int s){	//构造函数
        x = a;
        y = b;
        step = s;
    }
};
//所有操作都放在bfs()函数里面
void bfs(void)
{
	// 创建队列,并且将起始点加入该队列,作为搜索起点。
    queue<note> q;
    note t(1 , 1, 0);
    t.ans[t.step] = '\0';
    q.push(t);
    vis[0][0] = true;
    // 直到将所有路线搜索完
    while(!q.empty())
    {
        //取出队列的第一个元素
        note tt = q.front();
        q.pop();
        //判断是否满足搜索条件
        if(tt.x ==  30 && tt.y == 50)
        {
            tt.ans[tt.step] = '\0';		//将字符数组变成字符串,输出
            printf("\n%d\n%s\n", tt.step, tt.ans);
            break;
        }
        //不满足条件时,搜索其他位置,并且加入队列
        for( int i = 0; i < 4; i++ )
        {
            int x = tt.x + dir1[i][0];
            int y = tt.y + dir1[i][1];
            if(x >= 1 && y >= 1 && x <= 30 && y <= 50) // 必须先判断是否越界,再进行其他判断
            {
                if(!vis[x][y] && a[x][y] == '0')
                {
                	//产生新的搜索节点, 加入到队列中
                    note t3(x, y, tt.step + 1); 
                    for(int j = 0; j < tt.step; j++)
                        t3.ans[j] = tt.ans[j];
                    t3.ans[t3.step - 1] = dir2[i];
                    q.push(t3);
                    vis[x][y] = true;
                }
            }
        }
    }
}

int main()
{
    for(int i = 1; i <= 30; i++){
        for(int j = 1; j <= 50; j++){
            scanf("%c", &a[i][j]);
        }
        getchar();
    }
    bfs();
    return 0;
}

第十届蓝桥杯人物相关性目是一道经典的编程问,要求我们在给定的人物关系图中,判断两个人物之间是否存在一条关系链,即判断两个人物是否直接或间接地相关。 在这道目中,我们可以使用图的搜索算法来解决问。一种常见的算法是深度优先搜索(DFS),另一种是广度优先搜索(BFS)。 大概的思路是:首先,我们需要构建人物关系图,可以通过邻接矩阵、邻接表等数据结构来存储图的信息。然后,我们选择一个起始节点,从该节点开始进行搜索。如果在搜索的过程中找到了目标节点,即两个人物之间存在直接关系,那么我们可以结束搜索并返回结果。如果没有找到目标节点,则需要继续深入搜索,或者在广度搜索中扩展搜索队列。如果最终搜索完整个图都没有找到目标节点,那么可以判定两个人物之间不存在关系链。 具体实现时,可以使用递归或者栈来实现DFS,使用队列来实现BFS。在DFS中,我们可以利用函数的递归调用来实现深度搜索;在BFS中,我们可以通过队列不断地将待搜索节点加入队列,实现广度搜索。 总的来说,第十届蓝桥杯人物相关性目考察了对图的数据结构和搜索算法的掌握程度。需要我们理解并实现图的构建和搜索过程,进而判断两个人物之间的相关性。这道目不仅考察了编程基础知识,也锻炼了问分析和解决能力,是一道非常有挑战性的编程目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值