leetcode 2056.チェス盤での有効な移動の組み合わせの数(python)

一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して5日目です。クリックしてイベントの詳細をご覧ください

説明

n個(ルーク、クイーン、またはビショップ)を含む8x8のチェス盤があります。長さnの文字列配列piecesが与えられます。ここで、pieces [i]は、i番目のピースのタイプ(ルーク、クイーン、またはビショップ)を表します。さらに、長さnの2D整数配列位置が与えられます。ここで、positions [i] = [r i、c i ]は、i番目のピースが現在1ベースの座標(r i、c i)にあることを示します。チェス盤に。

ピースを移動するときは、ピースが移動して停止する目的の正方形を選択します。

  • ルークは、(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)。

ボード上のすべてのピースを同時に動かす必要があります。移動の組み合わせは、指定されたすべてのピースで実行されるすべての移動で構成されます。毎秒、各ピースは、まだ目的地に到達していない場合、目的地に向かって1マス瞬時に移動します。すべてのピースは0秒から移動を開始しますある時点で、2つ以上の駒が同じマスを占める場合、移動の組み合わせは無効です。

有効な移動の組み合わせの数を返します。

ノート:

  • 同じ正方形から2つのピースが始まることはありません。
  • ピースがすでにある正方形を目的地として選択できます。
  • 2つの部品が互いに直接隣接している場合、それらが互いに通過し、1秒間に位置を入れ替えることが有効です。

例1:

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

例2:

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

例3:

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

例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.
复制代码

例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.
复制代码

ノート:

  • n == piece.length
  • n == position.length
  • 1 <= n <= 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) 斜行

ボード上の各ピースを同時に移動します。すべてのチェスの駒は0秒から移動を開始し、移動の最後にすべてのチェスの駒の組み合わせがいくつあるかを示します。ある時点で、2つ以上の駒が同じマスを占める場合、移動の組み合わせは効果がありません。有効な移動の組み合わせの数を返します。

知らせ:

  • 同じ正方形から2つのピースが始まることはありません
  • チェスの駒が置かれているマス目を目的地として選択できます。つまり、移動することはできません。
  • 2つの部品が直接隣接している場合、それらは互いに移動し、1秒以内に位置を入れ替えることができます

実際、この質問の英語のタイトルの意味はあまり明確ではありません。主に、チェスの駒には3種類あり、それぞれの種類のチェスの駒の移動方法と、チェスの駒の停止には2つの状況があります。衝突。次に、ピースを動かした(または動かさなかった)後、ボード上の面の組み合わせがいくつ可能かを教えてください。制約を見ると、チェスの駒は最大4つ、クイーンは最大1つであることがわかります。チェス盤も小さく、各チェスの駒の移動位置も制限されています。この種の質問の方向性は、DFSを使用して、すべてのチェスの駒のすべての可能な位置を激しく横断することです。チェスの駒のすべての可能な組み合わせを見つけます。重要なのは、いくつかの小さなトリックにあります。Nビットを使用してすべてのピースのステータスを表す場合、1はまだ移動できることを意味し、0は0110などの停止を意味し、その方向の2番目と3番目のピースに1を追加するだけです。さらに、ハッシュメソッドを使用して既存のチェスの組み合わせを保存することもできます。これにより、多くの不要な再帰を減らすことができます。

答え

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
        	      
		
复制代码

運転結果

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.
复制代码

元のタイトルリンク:leetcode.com/problems/nu…

あなたのサポートは私の最大の動機です

おすすめ

転載: juejin.im/post/7083065922671345695
おすすめ