Ni Wendi te acompañará para conocer las vacaciones de invierno de la Blue Bridge Cup 2021. Una pregunta diaria: 1.26 (2019 Provincial Competition Group A Pregunta 4)

Habrá una pregunta todos los días durante las vacaciones de invierno de 2021, y la pregunta real para la competencia provincial de 2017 a 2019. El contenido de este artículo fue proporcionado por Ni Wendi (Clase 192, Departamento de Computación, Universidad de Ciencia y Tecnología de China Oriental) y Luo Yongjun. Una pregunta al día, siga la columna de la Copa Blue Bridge: https://blog.csdn.net/weixin_43914593/category_10721247.html

Proporcione códigos C ++, Java, Python en tres idiomas.

2019 Provincial Competition Group A Question 4 " Maze ", enlace del título:
http://oj.ecustacm.cn/problem.php?id=1455

Esta pregunta es una buena pregunta para que los principiantes entrenen.

1. Descripción del título


La siguiente figura muestra una vista en planta de un laberinto, donde los obstáculos marcados con 1 son obstáculos y los lugares marcados con 0 son lugares transitables.
010000
000100
001001
110000
La entrada del laberinto es la esquina superior izquierda, y la salida es la esquina inferior derecha. En el laberinto, solo se puede caminar desde una posición a una de sus cuatro direcciones, arriba, abajo, izquierda y derecha.
Para el laberinto de arriba, a partir de la entrada, puede atravesar el laberinto en el orden de DRRURRDDDR, un total de 10 pasos. Entre ellos, D, U, L y R significan bajar, subir, izquierda y derecha respectivamente.
Para el siguiente laberinto más complicado (30 filas y 50 columnas), busque una forma de atravesar el laberinto, que utilice el menor número de pasos. Bajo la premisa del menor número de pasos, busque el que tenga el menor número de pasos orden como respuesta.
Tenga en cuenta que D <L <R <U en orden lexicográfico.


2. Solución de problemas

  ¡Esta pregunta es excelente para practicar la búsqueda ! También existe la impresión de rutas , ¡que también debe dominarse!

  Aunque la imagen no es grande, no se puede contar dibujándola con las manos y mirándola con los ojos, solo se puede codificar, eso es lo que quiso decir el autor.
  No, no, algunas personas dicen que puedes obtener la respuesta dibujando a mano y contando los ojos: https://www.bbsmax.com/A/kmzLkg9XdG/ La
  persona que escribió la pregunta sigue siendo amable. El laberinto no es complicado y se puede contar a mano.

  La imagen de esta pregunta no es grande, por lo que se recomienda la búsqueda de fuerza bruta simple, no piense demasiado.
  ¿Es BFS o DFS?
  (1) ¿Quiere buscar todas las rutas posibles? Independientemente de si se utiliza BFS o DFS, la complejidad es exponencial.
  (2) El título solo requiere buscar la ruta más corta, que es mucho más simple, se debe utilizar BFS. BFS también es un algoritmo clásico para encontrar el camino más corto, sin embargo, solo se usa cuando la distancia entre nodos adyacentes es 1, que es el caso de esta pregunta.
  Para conocer el principio de BFS, consulte " 3 Naturaleza e implementación del código de BFS " en esta publicación de blog :
https://blog.csdn.net/weixin_43914593/article/details/104608578
  (3) Puede haber más de una ruta más corta , pero no es complicado. La característica de BFS es que se difunde capa por capa (al agregar nodos vecinos a la cola BFS, se agregan en el orden de distancia desde el punto de partida: primero une los nodos vecinos con una distancia de 1 desde el punto de partida, y luego agregarlos Nodos vecinos con una distancia de 2, etc.), después de buscar una capa, se buscará la siguiente capa. Un camino comienza desde el punto de partida y va gradualmente hacia afuera a lo largo de cada capa. Por cada capa adicional, la longitud del camino aumenta en 1. Luego, todos los caminos más cortos con la misma longitud se extienden desde el mismo nivel. Cuando se encuentra la primera ruta más corta al destino, la búsqueda continúa y se devolverán otras rutas que pueden no ser las más cortas.
  (4) La pregunta requiere devolver la ruta más corta con el orden lexicográfico más pequeño, por lo que siempre que se extienda a la siguiente capa (agregando nodos de la siguiente capa a la cola BFS), siga el orden lexicográfico "D <L <R < U Agregue los nodos de la siguiente capa en el orden de ”, luego el camino más corto encontrado primero es el que tiene el orden lexicográfico más pequeño.
  Así que esta pregunta es la ruta más corta de búsqueda básica de BFS. La complejidad es solo O (n) O (n)O ( n )nnn es el número total de nodos en el laberinto, esta pregunta tiene30 × 50 = 1500 30 \ times 50 = 15003 0×5 0=.1 .5 0 0 puntos. Porque cada punto se busca solo una vez, es decir, ingrese a la cola y salga de la cola una vez.
  Otra parte útil de esta pregunta es la impresión de rutas.Acontinuación se dandos métodos de impresión.

3. Dos métodos de impresión de ruta

   ¿Cómo imprimir la ruta? Una forma sencilla es: cada expansión hasta un punto vvv , todo envvv almacenar desde el punto de partidasss avvv 's ruta completaruta de rutap a t h . Llegar al finalttEn t , obtenemosssdesde el punto de partidas attEl camino completo de t . La desventaja de esto es que ocupa mucho espacio porque la ruta completa se almacena en cada punto.
   De hecho, no es necesario almacenar la ruta completa en el nodo, sino registrar su nodo precursor en cada punto, para que pueda retroceder desde el punto final hasta el punto de inicio y obtener una ruta completa (para una explicación detallada, consulte"Introducción a la competencia de algoritmos avanzada""Imprimir la ruta más corta" en la página 245). Llame a este método de grabación de ruta el "método estándar".
   El siguiente código muestra estos dos métodos de impresión de ruta respectivamente.

3.1 La forma sencilla

   De hecho, es muy sencillo: después de llegar al final, cout<<now.p<<endl;la ruta completa se imprime en una frase.
  (Tenga en cuenta que los dos códigos siguientes, enviados a oj.ecustacm.cn, son "respuestas incorrectas", porque esta es una pregunta para llenar el espacio en blanco, no hay entrada, solo salida. Puede ejecutarlo usted mismo para obtenga la respuesta e imprímala directamente cuando la envíe a OJ Eso es todo).

#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 Método estándar

   Tenga en cuenta print_path()que es una función recursiva, recursiva primero y luego imprime. Desde el punto final, vuelva al punto de inicio y luego imprima la ruta completa en orden positivo desde el punto de inicio hasta el punto final.

//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();
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43914593/article/details/112979575
Recomendado
Clasificación