Différents chemins III - Différents chemins III

980. Différents chemins III - LeetCode icon-default.png?t=N6B9https://leetcode.cn/problems/unique-paths-iii/description/

Sur une grille bidimensionnelle, il existe quatre types de carrés :

1 indique la case de départ. Et il n'y a qu'une seule grille de départ.
2 indique le carré de fin, et il n’y a qu’un seul carré de fin.
0 représente les cases vides que nous pouvons parcourir.
-1 est un obstacle que nous ne pouvons pas franchir.
Renvoie le nombre de chemins différents depuis la case de départ jusqu'à la case d'arrivée lors d'une marche dans quatre directions (haut, bas, gauche et droite).

Chaque case sans obstacle doit être franchie une fois, mais la même case ne peut pas être franchie plusieurs fois dans un chemin.

Sur une grille à deux dimensions  grid , il existe 4 types de carrés :

  • 1 Indique la case de départ. Et il n’y a qu’une seule case de départ.
  • 2 Indique le carré de fin, et il n’y a qu’un seul carré de fin.
  • 0 Représente une place vide que l’on peut parcourir.
  • -1 Représente un obstacle que nous ne pouvons pas surmonter.

Renvoie le nombre de chemins différents du carré de départ au carré de fin lors d'une marche dans quatre directions (haut, bas, gauche, droite) .

Chaque case sans obstacle doit être franchie une fois, mais la même case ne peut pas être franchie deux fois dans un parcours .

Exemple 1:

Entrée : [[1,0,0,0],[0,0,0,0],[0,0,2,-1]]
 Sortie : 2Explication
 : Nous avons les deux chemins suivants : 
1. (0 , 0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0 ) ,(2,1),(2,2) 
2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1) , (0,2),(0,3),(1,3),(1,2),(2,2)

Exemple 2 :

Entrée : [[1,0,0,0],[0,0,0,0],[0,0,0,2]]
 Sortie : 4
 Explication : Nous avons les quatre chemins suivants : 
1. (0, 0 ),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0) , (2,1),(2,2),(2,3) 
2. (0,0),(0,1),(1,1),(1,0),(2,0), ( 2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3) 3. 
(0,0),( 1 ,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0, 3 ),(1,3),(2,3) 
4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1 ) ,(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)

Exemple 3 :

Entrée : [[0,1],[2,0]]
 Sortie : 0
 Explication : 
Aucun chemin ne peut traverser complètement chaque case vide une fois. 
Notez que les carrés de début et de fin peuvent se trouver n'importe où dans la grille.

indice:

  • 1 <= grid.length * grid[0].length <= 20

Méthode 1 : revenir en arrière

S'il y a n zéros dans la matrice, alors un chemin qualifié est un chemin de longueur (n+1) qui commence par 1 et se termine par 2, ne passe pas par −1 et ne passe par chaque point qu'une seule fois. Pour connaître tous les chemins qualifiés, on peut utiliser la méthode du backtracking pour définir la fonction dfs, qui représente le nombre de chemins partant du point (i,j) et passant par n points jusqu'à la fin dans l'état actuel de la grille. Lorsqu'un point est atteint, si le point actuel est le point final et que (n+1) points ont été franchis, alors un chemin qualifié est formé, sinon il n'est pas formé. Si le point actuel n'est pas le point final, le point actuel est marqué comme −1, indiquant que le chemin ne peut pas passer ce point dans le futur, puis continuer à s'étendre dans quatre directions à ce point, s'il ne dépasse pas la limite. et la valeur du point suivant est 0 ou 2, cela signifie que le chemin peut continuer à s'étendre. Après avoir exploré les quatre directions, vous devez remplacer la valeur du point actuel par la valeur d'origine. La somme des chemins qualifiés dans les quatre directions correspond au nombre de chemins qualifiés dans l’état actuel. Le retour final est le nombre de chemins que la grille doit parcourir par (n+1) points à partir du point de départ dans son état initial.

Méthode 1 : retour en arrière

Idée : D'après les exigences, en supposant qu'il y ait n zéros dans la matrice, alors un chemin qualifié est un chemin de longueur (n+1), commençant à 1, se terminant à 2, ne passant pas par −1 et passant uniquement par chaque point. une fois. Pour connaître tous les chemins qualifiés, vous pouvez utiliser la méthode de backtracking et définir la fonction dfs, qui représente le nombre de chemins partant du point (i, j) et passant par n points jusqu'au point final dans l'état actuel de la grille. Lorsqu'on atteint un point, si le point actuel est le point final et a dépassé (n+1) points, alors un chemin qualifié est formé, sinon il n'est pas formé. Si le point actuel n'est pas le point final, marquez le point actuel comme −1, ce qui signifie que ce chemin ne pourra pas passer par ce point à l'avenir, puis continuer à s'étendre dans quatre directions à ce point. limite et la valeur du point suivant S'il est 0 ou 2, cela signifie que ce chemin peut continuer à s'étendre. Après avoir détecté les quatre directions, vous devez remplacer la valeur actuelle du point par la valeur d'origine. La somme des chemins qualifiés dans les quatre directions correspond au nombre de chemins qualifiés dans l’état actuel. Ce qui doit finalement être renvoyé, c'est le nombre de chemins que la grille doit parcourir (n+1) points à partir du point de départ dans son état initial.


class Solution {
    static int[][] dirs = {
   
   {-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public int uniquePathsIII(int[][] grid) {
        int r = grid.length, c = grid[0].length;
        int si = 0, sj = 0, n = 0;
        
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (grid[i][j] == 0) {
                    n++;
                } else if (grid[i][j] == 1) {
                    n++;
                    si = i;
                    sj = j;
                }
            }
        }
        return dfs(grid, si, sj, n);
    }

    public int dfs(int[][] grid, int i, int j, int n) {
        if (grid[i][j] == 2) {
            return n == 0 ? 1 : 0;
        }
        int r = grid.length, c = grid[0].length;
        int t = grid[i][j];
        grid[i][j] = -1;
        int res = 0;
        for (int[] dir : dirs) {
            int ni = i + dir[0], nj = j + dir[1];
            if (ni >= 0 && ni < r && nj >= 0 && nj < c && (grid[ni][nj] == 0 || grid[ni][nj] == 2)) {
                res += dfs(grid, ni, nj, n - 1);
            }
        }
        grid[i][j] = t;
        return res;
    }
}

 

Méthode 2 : Recherche mémorisée + compression d'état

Idée : méthode 1 de la fonction de retour en arrière, même dans le cas où i, j, n sont identiques, la valeur de retour de la fonction sera différente, car le chemin passant par le point est différent, ce qui donne la situation actuelle grille\textit L'état de la grille {grid} est également différent. Par conséquent, nous pouvons mettre l’état de la grille dans les paramètres d’entrée de la fonction, réduisant ainsi la complexité temporelle en mémorisant la recherche.

Un nombre binaire st est utilisé pour représenter le point par lequel le chemin n'est pas passé (l'état initial est constitué de tous les points ayant une valeur de 0 et du point final), et les coordonnées du point doivent correspondre aux bits du nombre binaire. Définissez la fonction dp, les paramètres d'entrée sont la coordonnée actuelle i,j et l'ensemble binaire st des points traversés, et la valeur de retour est le nombre de chemins partant du point (i,j), passant par l'ensemble de points représentés par st, et enfin atteindre le point final. Si le point actuel est le point final et qu'il ne reste plus aucun point non franchi, alors la valeur de retour actuelle est 1, sinon 0. Si le point actuel n'est pas le point final, vous devez explorer les quatre directions, si le point suivant est à l'intérieur de la limite et n'est pas encore passé (à en juger par l'opération bit-sum), vous devez vous rendre à ce point et supprimer les coordonnées de ce point de l'ensemble des points non transmis (déterminés par l'opération bit-sum). La somme des chemins qualifiés dans les quatre directions correspond au nombre de chemins qualifiés dans l’état actuel. La dernière chose qui doit être renvoyée est le nombre de chemins depuis le point de départ pour l'ensemble de points transmis à tous les points ayant une valeur de 0 et le point final. Une recherche mémorisée est utilisée lors de l'appel de la fonction, et chaque état est calculé au plus une fois. La dernière chose qui doit être renvoyée est le nombre de chemins depuis le point de départ pour l'ensemble de points transmis à tous les points ayant une valeur de 0 et le point final. Une recherche mémorisée est utilisée lors de l'appel de la fonction, et chaque état est calculé au plus une fois. La dernière chose qui doit être renvoyée est le nombre de chemins depuis le point de départ pour l'ensemble de points transmis à tous les points ayant une valeur de 0 et le point final. Une recherche mémorisée est utilisée lors de l'appel de la fonction, et chaque état est calculé au plus une fois.

Méthode 2 : Recherche de mémoire +
idée de compression d'état : fonction de retour en arrière de la méthode 1, même lorsque i, j, n sont identiques, la valeur de retour de la fonction sera différente, car les chemins passent par des points différents, ce qui entraîne la grille dans le situation actuelle Le statut de \textit{grid}grid est également différent. Par conséquent, nous pouvons mettre l'état de la grille dans les paramètres d'entrée de la fonction et utiliser la recherche mémorisée pour réduire la complexité temporelle.

Un nombre binaire st est utilisé pour représenter les points que le chemin n'a pas traversés (dans l'état initial, tous les points avec une valeur de 0 et le point final). Les coordonnées des points doivent correspondre aux bits du nombre binaire Un par un. Définissez la fonction dp. Les paramètres d'entrée sont les coordonnées actuelles i, j et l'ensemble binaire st des points de passage. La valeur de retour est le chemin partant du point (i, j), passant par l'ensemble des points représenté par st , et enfin atteindre le point final. Si le point actuel est le point final et qu'il ne reste plus aucun point non réussi, alors la valeur de retour actuelle est 1, sinon elle est 0. Si le point actuel n'est pas le point final, vous devez explorer quatre directions. Si le point suivant est à l'intérieur de la limite et n'a pas encore été dépassé (à en juger par l'opération de somme au niveau du bit), vous devez vous rendre à ce point et modifier les coordonnées. de ce point de ne jamais supprimer de l'ensemble des points de passage (en utilisant l'opération XOR au niveau du bit). La somme des chemins qualifiés dans les quatre directions correspond au nombre de chemins qualifiés dans l’état actuel. Ce qu'il faut finalement renvoyer, c'est le nombre de chemins partant du point de départ, l'ensemble des points de passage, tous les points ayant une valeur de 0 et le point final. La recherche mémorisée est utilisée lors de l'appel de la fonction, et chaque état ne sera calculé qu'une seule fois au maximum.

class Solution {
    static int[][] dirs = {
   
   {-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    Map<Integer, Integer> memo = new HashMap<Integer, Integer>();

    public int uniquePathsIII(int[][] grid) {
        int r = grid.length, c = grid[0].length;
        int si = 0, sj = 0, st = 0;
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (grid[i][j] == 0 || grid[i][j] == 2) {
                    st |= 1 << (i * c + j);
                } else if (grid[i][j] == 1) {
                    si = i;
                    sj = j;
                }
            }
        }
        return dp(grid, si, sj, st);
    }

    public int dp(int[][] grid, int i, int j, int st) {
        if (grid[i][j] == 2) {
            return st == 0 ? 1 : 0;
        }
        int r = grid.length, c = grid[0].length;
        int key = ((i * c + j) << (r * c)) + st;
        if (!memo.containsKey(key)) {
            int res = 0;
            for (int[] dir : dirs) {
                int ni = i + dir[0], nj = j + dir[1];
                if (ni >= 0 && ni < r && nj >= 0 && nj < c && (st & (1 << (ni * c + nj))) > 0) {
                    res += dp(grid, ni, nj, st ^ (1 << (ni * c + nj)));
                }
            }
            memo.put(key, res);
        }
        return memo.get(key);
    }
}

 

Je suppose que tu aimes

Origine blog.csdn.net/m0_72572822/article/details/132097187
conseillé
Classement