"""
给定一个二维网格和一个单词，找出该单词是否存在于网格中。

单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

 

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
 

提示：

board 和 word 中只包含大写和小写英文字母。
1 <= board.length <= 200
1 <= board[i].length <= 200
1 <= word.length <= 10^3

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/word-search
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
check(i, j, k): 从矩阵的第i，j位置出发，能否遍历出word[k:]
"""

import numpy as np
from typing import *


class Solution:
    def check(self, board, word, mark, i, j, k):
        if k == len(word):
            return True

        if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != word[k] or mark[i][j] == 1:
            return False
        mark[i][j] = 1
        if self.check(board, word, mark, i - 1, j, k + 1):
            return True
        if self.check(board, word, mark, i + 1, j, k + 1):
            return True
        if self.check(board, word, mark, i, j - 1, k + 1):
            return True
        if self.check(board, word, mark, i, j + 1, k + 1):
            return True
        mark[i][j] = 0
        return False

    def exist(self, board: List[List[str]], word: str) -> bool:
        rows, cols = len(board), len(board[0])
        for i in range(rows):
            for j in range(cols):
                mark = np.zeros((rows, cols))
                if self.check(board, word, mark, i, j, 0):
                    return True
        return False


if __name__ == '__main__':
    s = Solution()
    print(s.exist([["A","B","C","E"],
                   ["S","F","E","S"],
                   ["A","D","E","E"]],
                  "ABCESEEEFS"))
