Ni Wendi will accompany you to learn the Blue Bridge Cup 2021 Winter Holiday. One question daily: 1.26 (2019 Provincial Competition Group A Question 4)

There will be one question every day during the winter vacation of 2021, and the real question for the provincial competition from 2017 to 2019. The content of this article was provided by Ni Wendi (Class 192, Computer Department, East China University of Science and Technology) and Luo Yongjun. One question a day, follow the Blue Bridge Cup column: https://blog.csdn.net/weixin_43914593/category_10721247.html

Provide C++, Java, Python codes in three languages.

2019 Provincial Competition Group A Question 4 " Maze ", title link:
http://oj.ecustacm.cn/problem.php?id=1455

This question is a good question for beginners to train.

1. Title description


The following figure shows a plan view of a maze, where the obstacles marked 1 are obstacles, and the places marked 0 are passable places.
010000
000100
001001
110000
The entrance of the maze is the upper left corner, and the exit is the lower right corner. In the maze, you can only walk from one position to one of its four directions, up, down, left and right.
For the maze above, starting from the entrance, you can pass through the maze in the order of DRRURRDDDR, a total of 10 steps. Among them, D, U, L, and R mean go down, up, left, and right respectively.
For the following more complicated maze (30 rows and 50 columns), please find a way to pass through the maze, which uses the least number of steps. Under the premise of the least number of steps, please find the one with the least lexicographical order as the answer.
Please note that D<L<R<U in lexicographic order.


2. Problem solution

  This question is great for practicing search ! There is also path printing , which also needs to be mastered!

  Although the picture is not big, it can't be counted by drawing it with your hands and looking at it with your eyes. It can only be coded. That's what the author meant.
  No, no, some people say that you can get the answer by hand drawing and counting the eyes: https://www.bbsmax.com/A/kmzLkg9XdG/ The
  person who wrote the question is still kind. The maze is not complicated, and it can be counted by hand.

  The picture of this question is not big, so simple brute force search is encouraged, don't think too much.
  Is it BFS or DFS?
  (1) Do you want to search all possible paths? Regardless of whether BFS or DFS is used, the complexity is exponential.
  (2) The title only requires searching the shortest path, which is much simpler. BFS must be used. BFS is also a classic algorithm for finding the shortest path, but it is only used when the distance between adjacent nodes is 1, which is the case of this question.
  For the principle of BFS, refer to " 3 Nature and Code Implementation of BFS " in this blog post :
https://blog.csdn.net/weixin_43914593/article/details/104608578
  (3) There may be more than one shortest path, but it is not complicated. The characteristic of BFS is that it is diffused layer by layer (when adding neighbor nodes to the BFS queue, they are added in the order of distance from the starting point: first join the neighbor nodes with a distance of 1 from the starting point, and then add them. Neighbor nodes with a distance of 2, etc.), after searching one layer, the next layer will be searched. A path starts from the starting point and gradually goes outward along each layer. For each additional layer, the length of the path increases by 1. Then, all the shortest paths with the same length spread out from the same level. When the first shortest path to the destination is found, the search continues, and other paths that may not be the shortest will be returned.
  (4) The question requires returning the shortest path with the smallest lexicographic order, so as long as it spreads to the next layer (adding nodes of the next layer to the BFS queue), follow the lexicographic order "D<L<R<U Add the nodes of the next layer in the order of ”, then the shortest path found first is the one with the smallest lexicographic order.
  So this question is a basic BFS search shortest path. The complexity is only O (n) O(n)O ( n )nnn is the total number of nodes in the maze, this question has30 × 50 = 1500 30\times 50=150030×50=. 1 . 5 0 0 points. Because each point is searched only once, that is, enter the queue and leave the queue once.
  Another useful part of this question is path printing.Two printing methodsare given below.

3. Two path printing methods

   How to print the path? A simple way is: every expansion to a point vvv , all invvv store from the starting pointsss tovvv 's full pathpath pathp a t h . Reach the endttAt t , we getssfrom the starting points tottThe full path of t . The disadvantage of this is that it takes up a lot of space because the complete path is stored at each point.
   In fact, it is not necessary to store the complete path on the node, but to record its predecessor node at each point, so that you can step back from the end point to the starting point and get a complete path (for detailed explanation, see"Introduction to Algorithm Competition" Advanced""Print Shortest Path" on page 245). Call this path recording method the "standard method".
   The following code demonstrates these two path printing methods respectively.

3.1 The simple way

   It is very simple indeed. After reaching the end, cout<<now.p<<endl;the complete path is printed out in one sentence.
  (Note that the following two codes, submitted to oj.ecustacm.cn, are all "answers wrong", because this is a fill-in-the-blank question, there is no input, only output. You can run it yourself to get the answer, and print the answer directly when you submit it to OJ That's it.)

#include<bits/stdc++.h>
using namespace std;
struct node{
    
    
    int x;
    int y;
    string p;  //path,记录从起点(0,0)到这个点(x,y)的完整路径
};
char a[31][51];  //存地图

char k[4]={
    
    'D','L','R','U'};
int dir[4][2]={
    
    {
    
    1,0},{
    
    0,-1},{
    
    0,1},{
    
    -1,0}};
int vis[30][50];  //标记。vis=1: 已经搜过,不用再搜
void bfs(){
    
    
    node start; start.x=0;  start.y=0;   start.p="";  //定义起点
    vis[0][0]=1;              //标记起点被搜过

    queue<node>q;   q.push(start);   //把第一个点放进队列,开始BFS
    while(!q.empty()){
    
    
        node now = q.front();  //取出队首
        q.pop();
        if(now.x==29 && now.y==49){
    
     //第一次达到终点,这就是字典序最小的最短路径
            cout<<now.p<<endl;       //打印路径:从(0,0)到(29,49)
            return;
        }
        for(int i=0;i<4;i++){
    
      //扩散邻居结点
            node next;
            next.x = now.x+dir[i][0];
            next.y = now.y+dir[i][1];
            if(next.x<0||next.x>=30||next.y<0||next.y>=50)  //越界了
                continue;
            if(vis[next.x][next.y]==1||a[next.x][next.y]=='1')  //vis=1:已经搜过;  a=1:是障碍
                continue;
            vis[next.x][next.y]=1;  //标记被搜过
            next.p = now.p+k[i];  //记录完整路径:把上一个点的路径,加上这一步后,复制给下一个点
            q.push(next);
        }
    }
}
int main(){
    
    
    for(int i=0;i<30;i++)  cin>>a[i];  //读题目给的地图数据
    bfs();
}

3.2 Standard method

   Note print_path()that it is a recursive function, recursive first and then print. From the end point, back to the start point, and then print out the complete path in the positive order from the start point to the end point.

//User: 19031010128
#include<bits/stdc++.h>
using namespace std;
struct node{
    
    
    int x;
    int y;
};
char a[31][51];  //存地图

char k[4]={
    
    'D','L','R','U'};
int dir[4][2]={
    
    {
    
    1,0},{
    
    0,-1},{
    
    0,1},{
    
    -1,0}};
int vis[30][50];  //1:已经搜过,不用再搜

char pre[31][51]; //用于查找前驱点。例如pre[x][y] = ‘D’,表示上一个点往下走一步到了(x,y),那么上一个点是(x-1,y)
void print_path(int x,int y){
    
          //打印路径:从(0,0)到(29,49)
  if(x==0 && y==0)   //回溯到了起点,递归结束,返回
     return;
  if(pre[x][y]=='D')  print_path(x-1,y);   //回溯,往上 U
  if(pre[x][y]=='L')  print_path(x,  y+1); //回溯,往右 R
  if(pre[x][y]=='R')  print_path(x,  y-1);
  if(pre[x][y]=='U')  print_path(x+1,y);
  printf("%c",pre[x][y]);                  //最后打印的是终点
}

void bfs(){
    
    
    node now,next;
    queue<node>q;
    now.x=0;
    now.y=0;
    vis[0][0]=1;
    q.push(now);

    while(!q.empty()){
    
    
        now=q.front();
        q.pop();
        if(now.x==29 && now.y==49){
    
     //第一次达到终点,这就是字典序最小的最短路径
            print_path(29,49);      //打印路径,从终点回溯到起点。但是打印出来是从起点到终点的正序
            return;
        }
        for(int i=0;i<4;i++){
    
    
            next.x = now.x+dir[i][0];
            next.y = now.y+dir[i][1];
             if(next.x<0||next.x>=30||next.y<0||next.y>=50)  //越界
                continue;
            if(vis[next.x][next.y]==1||a[next.x][next.y]=='1')  //vis=1:已经搜过;  a=1,是障碍
                continue;
            vis[next.x][next.y]=1;
            pre[next.x][next.y] = k[i];   //记录点(x,y)的前驱
            q.push(next);
        }
    }
}
int main(){
    
    
    for(int i=0;i<30;i++)  cin>>a[i];  //读题目给的地图数据,30行,每行50个
    bfs();
}

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/112979575