[JAVA] Mesurez la distance du labyrinthe avec la recherche de priorité de largeur

Participez à ABC151 et résumez comme un examen qui n'a pas pu résoudre le problème D

Recherche de priorité de largeur et recherche de priorité de profondeur

Regardez le diagramme wiki parce qu'il est si facile à comprendre ...

Eh bien, je pensais qu'il y avait un arbre comme celui-ci

Parent A
├ Enfant AA
│ ├ Fils AAA
│ └ Fils AAB
├ Enfant AB
│ └ Fils ABA
└ Enfant AC
├ Fils ACA
├ Son ACB
└ Son ACC

Recherche de priorité de largeur

https://ja.wikipedia.org/wiki/%E5%B9%85%E5%84%AA%E5%85%88%E6%8E%A2%E7%B4%A2

Recherchez tous les nœuds enfants suspendus au nœud parent, puis recherchez tous les nœuds petits-enfants suspendus au nœud enfant recherché.

Résoudre à l'aide d'une file d'attente

  1. Mettez le parent A dans la file d'attente (état de la file d'attente: parent A)
  2. Extraire le parent A (état de la file d'attente: vide)
  3. Mettre en file d'attente tous les enfants AA, AB, AC suspendus au parent A (état de la file d'attente: enfant AA enfant AB enfant AC)
  4. Retirez l'enfant AA (état de la file d'attente: enfant AB enfant AC)
  5. Mettre en file d'attente tous les petits-enfants AAA et AAB suspendus à l'enfant AA (état de la file d'attente: enfant AB enfant AC petit-enfant AAA petit-enfant AAB)
  6. Répétez jusqu'à ce que la file d'attente soit vide

L'ordre de recherche est Parent A → Enfant AA → Enfant AB → Enfant AC → Petit-enfant AAA → Petit-enfant AAB → Petit-enfant ABA → Petit-enfant ACA → Petit-enfant ACB → Petit-enfant ACC

La recherche de priorité de largeur consiste à rechercher dans l'ordre parent → enfant → petit-enfant

Recherche de priorité de profondeur

https://ja.wikipedia.org/wiki/%E6%B7%B1%E3%81%95%E5%84%AA%E5%85%88%E6%8E%A2%E7%B4%A2

Allez aussi loin que possible du nœud parent, puis revenez en arrière et recherchez d'autres nœuds enfants.

Ceci est une pile, c'est premier entré, premier sorti

  1. Mettez le parent A dans la pile (état de la pile: parent A)
  2. Récupérer le parent A (état de la pile: vide)
  3. Mettez les enfants AA, AB, AC suspendus au parent A dans la pile (état de la pile: Child AA Child AB Child AC)
  4. Sortez le CA enfant (état de la pile: enfant AA enfant AB)
  5. Placez le petit-enfant ACA, ACB, ACC suspendu à l'AC enfant dans la pile (état de la pile: Enfant AA Enfant AB Petit-enfant ACB Petit-enfant ACB Petit-enfant ACC)
  6. Répétez jusqu'à ce que la pile soit vide

L'ordre de recherche est Parent A → Enfant AC → Petit-enfant ACC → Petit-enfant ACB → Petit-enfant ACA → Enfant AB → Petit-enfant ABA → Enfant AA → Petit-enfant AAA → Petit-enfant AAB

C'est une image de regarder la circonférence extérieure de l'arbre dans l'ordre, mais elle est transmise ...

J'ai écrit qu'il utilise une pile, mais si vous effectuez une recherche récursive, ce sera une recherche prioritaire en profondeur (ne pouvez-vous pas dire cela en général?)

Problème non résolu

https://atcoder.jp/contests/abc151/tasks/abc151_d

D - Maze Master

Énoncé du problème

M. Takahashi a un labyrinthe composé de carrés H × W avec des carrés H verticaux et des carrés W horizontaux. La cellule (i, j) dans la i-ème rangée à partir du haut et la j-ème colonne à partir de la gauche est le mur lorsque Sij est # '' et la route lorsque Sij est. ''. À partir de la place de la route, vous pouvez vous déplacer vers la place de la route qui est adjacente en haut, en bas, à gauche et à droite. Vous ne pouvez pas sortir du labyrinthe, vous déplacer vers un carré de mur ou vous déplacer en diagonale. Takahashi décide librement du départ et du but depuis la place de la route et remet le labyrinthe à Aoki. Aoki se déplace du début au but avec le nombre minimum de coups. Quand Takahashi positionne correctement le départ et le but, combien de fois Aoki se déplacera-t-il au maximum?

Contrainte

1≤H,W≤20 Sij est .'` Ou # '' S contient au moins deux ``. '' Vous pouvez atteindre n'importe quelle place de route à partir de n'importe quelle place de route avec 0 mouvements ou plus

contribution

L'entrée est donnée à partir de l'entrée standard dans le format suivant.

H W
S11...S1W
:
SH1...SHW

Répondre

import java.util.*;

public class Main {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        String[] params = in.nextLine().split(" ");
        int h = Integer.parseInt(params[0]);
        int w = Integer.parseInt(params[1]);
        String[][] ss = new String[h][w];
        for (int i = 0; i < h; i++) {
            params = in.nextLine().split("");
            for (int j = 0; j < w; j++) {
                ss[i][j] = params[j];
            }
        }

        //Répondez à la plus longue distance à partir de tous les lieux
        int maxDistance = 0;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                maxDistance = Math.max( maxDistance , getMaxDistanceWithBfs( ss , i , j ) );
            }
        }

        System.out.println(maxDistance);

    }

    /**
     *Renvoie la plus longue distance dans la recherche de priorité de largeur
     * @tableau de labyrinthe param ss
     * @param startY Coordonnée Y du point de départ
     * @param startX Coordonnée X du point de départ
     * @retour la plus longue distance
     */
    private static int getMaxDistanceWithBfs( String[][] ss , int startY , int startX ) {

        int[][] distances = new int[ss.length][ss[0].length];
        Queue<Integer> queue = new ArrayDeque<>();

        //Définition des distances de tous côtés en haut à gauche en bas à droite
        int[] dx = { -1 , 0 , 1 , 0 };
        int[] dy = { 0 , 1 , 0 , -1 };

        int maxDistance = 0;

        //Ajouter la position de départ à la file d'attente
        queue.add( startX );
        queue.add( startY );

        //Lorsque la file d'attente est vide=Quand il n'y a plus d'endroits à explorer
        //Nombre de boucles=Distance par rapport à la position de départ
        while( !queue.isEmpty()  ) {

            int x = queue.remove();
            int y = queue.remove();

            //Si l'emplacement actuel est un mur, ne traitez pas
            if( "#".equals( ss[y][x] ) ){
                continue;
            }

            maxDistance = Math.max( maxDistance , distances[y][x] );

            //Vérifiez tous les côtés
            for( int i = 0 ; i < 4 ; i++ ){

                //Confirmation des coordonnées de destination
                int xx = x + dx[i];
                int yy = y + dy[i];

                //Les coordonnées de destination de confirmation ne sont pas en dehors du tableau
                if( !( 0 <= yy && yy < ss.length && 0 <= xx && xx < ss[0].length ) ) {
                    continue;
                }

                //Les coordonnées de destination de confirmation ne sont pas des murs
                if( !".".equals( ss[yy][xx] ) ) {
                    continue;
                }

                //Pas la route que tu as déjà prise
                if( distances[yy][xx] != 0 ){
                    continue;
                }

                //Pas le point de départ
                if( xx == startX && yy == startY ){
                    continue;
                }

                queue.add( xx );
                queue.add( yy );
                distances[yy][xx] = distances[y][x] + 1;

            }

        }

        return maxDistance;

    }

}

Vérifiez tous les côtés des coordonnées extraites de la file d'attente et ajoutez-le à la file d'attente s'il s'agit d'un chemin À ce moment-là, stockez-le dans un endroit où vous pouvez dépasser la distance actuelle +1

Parce que j'ai écrit le tableau de jugement pour savoir s'il est passé ou non avec le tableau qui stocke la distance depuis le point de départ Je devais aussi voir si les coordonnées de destination de confirmation étaient le point de départ

3 5
#####
#..##
#####

Répondez 1 avec S22 comme point de départ et S23 comme point de but est la bonne réponse lorsque c'est le cas. Lorsque vous mesurez la distance depuis le point de départ,

#####
#0.##
#####
#####
#01##
#####
#####
#21##
#####

Ainsi, l'itinéraire le plus long est de revenir en arrière après avoir jugé que le point de départ (distance du point de départ: 0) n'est pas encore passé. Il semble qu'il y avait quelque chose de similaire à ce qui précède dans le jugement, donc quand j'ai décoché, c'est devenu WA correctement

Java a une classe de coordonnées appelée Point en standard, alors j'aurais peut-être dû l'utiliser Je n'en avais pas besoin car j'ai décidé d'en ajouter / supprimer 2 chacun dans l'ordre X → Y dans la file d'attente.

Remarques

Comment puis-je faire glisser toutes les coordonnées comme point de départ?

Le problème cette fois est que la taille du tableau bidimensionnel est jusqu'à 20 x 20 Même si j'ai vérifié tous les emplacements comme point de départ, il y avait une marge dans le temps d'exécution. Est-ce impossible s'il s'élargit? Souhaitez-vous utiliser le même calcul d'itinéraire? Sera-ce plus rapide que cette écriture?

J'ai regardé les réponses des autres Il semble que ce problème doit être balayé

Il serait peut-être préférable d'examiner d'autres problèmes en utilisant la recherche de priorité de largeur

1/13 Correction de la source de réponse

Quand j'ai écrit cet article, je l'ai écrit comme ça au début https://atcoder.jp/contests/abc151/submissions/9485696

Points de correction

C'est le vôtre

Nous n'avons plus besoin de System.arraycopy car nous devons préparer un tableau pour mesurer la distance de chaque coordonnée.

Avant correction.java


//Passez une copie lorsque vous manipulez le tableau pendant la recherche
for( int k = 0 ; k < h ; k++ ){
    copy[k] = new String[w];
    System.arraycopy( ss[k] , 0 , copy[k] , 0 , w );
}
int distance = getMaxDistanceWithBfs( copy , i , j );

Conçu pour utiliser la classe de mathématiques

C'est pratique ...

Avant correction.java


int distance = getMaxDistanceWithBfs( copy , i , j );
if (maxDistance < distance) {
    maxDistance = distance;
}

Si vous décidez de mettre dans la file d'attente dans l'ordre X → Y, vous n'avez pas besoin d'une classe de coordonnées

Avant correction.java


/**
 *Classe de coordonnées
 */
public static class Position {
    int x;
    int y;
    public Position( int x , int y ) {
        this.x = x;
        this.y = y;
    }
}

Queue<Position> queue = new ArrayDeque<>();
queue.add( new Position( startX , startY ) );

J'ai changé le traitement de la boucle

Avant correction.java


return distance - 1;

Je déteste vraiment ce livre qui suit

À l'origine

  1. Bouclez jusqu'à ce que la file d'attente soit vide
  2. Boucle pour voir tout ce qui est à la même distance que celui sorti
  3. Vérifiez tous les côtés (pourquoi ne pas utiliser pour) Triple boucle

En préparant un tableau pour stocker la distance de chaque coordonnée, la boucle de 2 n'est plus nécessaire. La boucle 2 était nécessaire pour mesurer la distance, mais pour une raison quelconque, elle devait finalement être distance-1

Recommended Posts

Mesurez la distance du labyrinthe avec la recherche de priorité de largeur
Vérifiez le contenu des paramètres avec le levier
Mesurez facilement la taille des objets Java
À propos du traitement de BigDecimal (avec réflexion)
Mettre en forme le contenu de LocalDate avec DateTimeFormatter
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Introduction aux algorithmes avec java --Search (recherche de priorité de largeur)
Vérifiez le contenu de l'objet argument avec Mockito
Gérez la version de Ruby elle-même avec rbenv
Écraser le contenu de la configuration avec Spring-boot + JUnit5
L'histoire du réglage de l'application Android avec libGDX
Préparez l'environnement CentOS 8 avec Sakura VPS
Spécifiez la valeur par défaut avec @Builder of Lombok
J'ai vérifié le nombre de taxis avec Ruby
JavaFX --Match la taille d'ImageView avec d'autres nœuds
CI l'architecture des applications Java / Kotlin avec ArchUnit
[JUnit 5] Traiter de "la référence d'assertEquals est ambiguë"
Accédez au h2db intégré de Spring Boot avec jdbcTemplate
Tester le contenu d'un fichier Excel avec JUnit
L'histoire de la création d'un proxy inverse avec ProxyServlet
Surveillez l'état interne des programmes Java avec Kubernetes
Implémentez iOS14 UICollectionView avec le code minimum requis.
Vérifiez le comportement de Java Intrinsic Locks avec bpftrace
Vérifiez le résultat de l'inférence de paramètre de type générique avec JShell
À peu près le flux de développement d'applications Web avec Rails.
Contrôlez le flux de traitement Spring Batch avec JavaConfig.
L'histoire de la création de DTO, semblable à Dao avec Java, SQLite
Remplacez seulement une partie de l'hôte URL par java