leetcode 2056. Número de combinaciones de movimientos válidas en el tablero de ajedrez (python)

¡Acostúmbrate a escribir juntos! Este es el quinto día de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .

describir

Hay un tablero de ajedrez de 8 x 8 que contiene n piezas (torres, reinas o alfiles). Se le proporciona una matriz de cadenas de piezas de longitud n, donde piezas[i] describe el tipo (torre, reina o alfil) de la i -ésima pieza. Además, se le proporciona una matriz de enteros 2D de posiciones también de longitud n, donde las posiciones [i] = [r i , c i ] indican que la i -ésima pieza se encuentra actualmente en la coordenada basada en 1 (r i , c i ) en el tablero de ajedrez.

Cuando haces un movimiento por una pieza, eliges una casilla de destino hacia la que viajará la pieza y se detendrá.

  • Una torre solo puede viajar horizontal o verticalmente desde (r, c) hacia la dirección de (r+1, c), (r-1, c), (r, c+1) o (r, c-1) .
  • Una reina solo puede viajar horizontal, vertical o diagonalmente desde (r, c) hacia la dirección de (r+1, c), (r-1, c), (r, c+1), (r, c- 1), (r+1, c+1), (r+1, c-1), (r-1, c+1), (r-1, c-1).
  • Un alfil solo puede viajar en diagonal desde (r, c) en la dirección de (r+1, c+1), (r+1, c-1), (r-1, c+1), (r-1 , c-1).

Debes hacer un movimiento para cada pieza en el tablero simultáneamente. Una combinación de movimientos consta de todos los movimientos realizados en todas las piezas dadas. Cada segundo, cada pieza viajará instantáneamente un cuadrado hacia su destino si aún no lo han hecho. Todas las piezas comienzan a viajar en el segundo 0 . Una combinación de movimientos no es válida si, en un momento dado, dos o más piezas ocupan la misma casilla.

Devuelve el número de combinaciones de movimientos válidas​​​​​.

Notas:

  • No habrá dos piezas que comiencen en el mismo cuadrado.
  • Puede elegir la casilla en la que ya se encuentra una pieza como su destino.
  • Si dos piezas están directamente una al lado de la otra, es válido que pasen una al lado de la otra e intercambien posiciones en un segundo.

Ejemplo 1:

Input: pieces = ["rook"], positions = [[1,1]]
Output: 15
Explanation: The image above shows the possible squares the piece can move to.
复制代码

Ejemplo 2:

Input: pieces = ["queen"], positions = [[1,1]]
Output: 22
Explanation: The image above shows the possible squares the piece can move to.
复制代码

Ejemplo 3:

Input: pieces = ["bishop"], positions = [[4,3]]
Output: 12
Explanation: The image above shows the possible squares the piece can move to.
复制代码

Ejemplo 4:

Input: pieces = ["rook","rook"], positions = [[1,1],[8,8]]
Output: 223
Explanation: There are 15 moves for each rook which results in 15 * 15 = 225 move combinations.
However, there are two invalid move combinations:
- Move both rooks to (8, 1), where they collide.
- Move both rooks to (1, 8), where they collide.
Thus there are 225 - 2 = 223 valid move combinations.
Note that there are two valid move combinations that would result in one rook at (1, 8) and the other at (8, 1).
Even though the board state is the same, these two move combinations are considered different since the moves themselves are different.
复制代码

Ejemplo 5:

Input: pieces = ["queen","bishop"], positions = [[5,7],[3,4]]
Output: 281
Explanation: There are 12 * 24 = 288 move combinations.
However, there are several invalid move combinations:
- If the queen stops at (6, 7), it blocks the bishop from moving to (6, 7) or (7, 8).
- If the queen stops at (5, 6), it blocks the bishop from moving to (5, 6), (6, 7), or (7, 8).
- If the bishop stops at (5, 2), it blocks the queen from moving to (5, 2) or (5, 1).
Of the 288 move combinations, 281 are valid.
复制代码

Nota:

  • n == piezas.longitud
  • n == posiciones.longitud
  • 1 <= norte <= 4
  • pieces only contains the strings "rook", "queen", and "bishop".
  • There will be at most one queen on the chessboard.
  • 1 <= xi, yi <= 8
  • Each positions[i] is distinct.

解析

根据题意,有一个 8 x 8 的棋盘,包含 n 个棋子(车、皇后或主教)。给定一个长度为 n 的字符串数组 pieces,其中 pieces[i] 描述了第 i 个片段的类型(车、王后或主教)。此外给出一个长度为 n 的二维整数数组 positions ,其中 positions[i] = [ri, ci] 表示第 i 个棋子当前位于棋盘上的从 1 开始的的坐标 (ri, ci) 上。

当棋子移动时,可以选择棋子将行进并停在的目标方格:

  • 车只能从(r,c)向(r+1,c)、(r-1,c)、(r,c+1)或(r,c-1)的方向水平或垂直移动
  • 皇后只能水平、垂直或斜行从 (r, c) 到 (r+1, c) 、(r-1, c) 、(r, c+1) 、(r, c- 1) 、 (r+1, c+1) 、(r+1, c-1) 、(r-1, c+1) 、(r-1, c-1)
  • 主教只能从 (r, c) 向 (r+1, c+1) 、(r+1, c-1) 、 (r-1, c+1) 、(r-1, c-1) 斜行

Mueve cada pieza en el tablero al mismo tiempo. Todas las piezas de ajedrez comienzan a viajar desde el segundo 0, y cuántas combinaciones hay para todas las piezas de ajedrez al final de su viaje. Si en un momento dado, dos o más piezas ocupan la misma casilla, la combinación de movimientos no tiene efecto. Devuelve el número de combinaciones de movimientos válidas.

Aviso:

  • No hay dos piezas que comiencen en el mismo cuadrado.
  • Puedes elegir la casilla donde se encuentra la pieza de ajedrez como destino, es decir, no puedes moverte
  • Si dos piezas están directamente una al lado de la otra, pueden moverse entre sí e intercambiar posiciones en un segundo.

De hecho, el significado del título en inglés de esta pregunta no está muy claro. Dice principalmente que hay tres tipos de piezas de ajedrez, cada tipo de pieza de ajedrez tiene un método de viaje y la parada de la pieza de ajedrez tiene dos situaciones: fuera de límites y colisión. Luego dinos cuántas combinaciones de caras en el tablero son posibles después de mover (o no mover) las piezas. Mirando las restricciones, se encuentra que hay como máximo 4 piezas de ajedrez, y solo hay una reina como máximo. El tablero de ajedrez también es pequeño, y la posición de viaje de cada pieza de ajedrez también es limitada. Es obvio que el general La dirección de este tipo de pregunta es usar DFS para atravesar violentamente todas las posiciones posibles de todas las piezas de ajedrez, encontrar todas las combinaciones posibles de caras de ajedrez. La clave está en algunos pequeños trucos. Si se usan N bits para representar el estado de todas las piezas, 1 significa que aún puede moverse, 0 significa detenerse, como 0110, luego solo agregue 1 a la segunda y tercera pieza en su dirección. Además, también puede usar el método hash para guardar las combinaciones de ajedrez existentes, lo que puede reducir una gran cantidad de recursividad innecesaria.

responder

class Solution(object):
    def __init__(self):
        self.result = set()
        self.dir = [[-1, 0], [1, 0], [0, -1], [0, 1], [1, 1], [1, -1], [-1, 1], [-1, -1]]
        self.N = 0

    def countCombinations(self, pieces, positions):
        """
        :type pieces: List[str]
        :type positions: List[List[int]]
        :rtype: int
        """
        self.N = len(pieces)
        for state in range(1 << (3 * self.N)):
            flag = 1
            dirs = [0] * self.N
            for k in range(self.N):
                d = (state >> (3 * k)) % 8
                if pieces[k] == 'rook' and d > 3:
                    flag = 0
                    break
                if pieces[k] == 'bishop' and d < 4:
                    flag = 0
                    break
                dirs[k] = d
            if flag:
                self.dfs(positions, dirs, (1 << self.N) - 1)
        return len(self.result) + 1

    def dfs(self, positions, dirs, state):
        subset = state
        while subset>0:
            pos2 = copy.deepcopy(positions)
            flag = 1
            for i in range(self.N):
                if (subset >> i) & 1:
                    pos2[i][0] += self.dir[dirs[i]][0]
                    pos2[i][1] += self.dir[dirs[i]][1]
                    if pos2[i][0] < 1 or pos2[i][0] > 8:
                        flag = 0
                        break
                    if pos2[i][1] < 1 or pos2[i][1] > 8:
                        flag = 0
                        break

            if flag == 0:
                subset = (subset - 1) & state
                continue
            if self.duplicate(pos2):
                subset = (subset - 1) & state
                continue

            hash = self.getMyHash(pos2)
            if hash in self.result:
                subset = (subset - 1) & state
                continue
            self.result.add(hash)
            self.dfs(pos2, dirs, subset)
            subset = (subset - 1) & state


    def duplicate(self, pos):
        for i in range(self.N):
            for j in range(i + 1, self.N):
                if pos[i] == pos[j]:
                    return True
        return False

    def getMyHash(self, pos):
        result = 0
        for i in range(self.N):
            result = result * 10 + pos[i][0]
            result = result * 10 + pos[i][1]
        return result
        	      
		
复制代码

resultado de la operación

Runtime: 5016 ms, faster than 27.12% of Python online submissions for Number of Valid Move Combinations On Chessboard.
Memory Usage: 17.7 MB, less than 44.07% of Python online submissions for Number of Valid Move Combinations On Chessboard.
复制代码

Enlace del título original: leetcode.com/problems/nu…

Tu apoyo es mi mayor motivación.

Supongo que te gusta

Origin juejin.im/post/7083065922671345695
Recomendado
Clasificación