BFS + MinHeap
javascript []\nclass MinMaxPriorityQueue {\n\n  #heap = []\n  #compare;\n\n  constructor(compare) {\n    this.#heap = [];\n    this.#compare = compare || ((a, b
```javascript []\nclass MinMaxPriorityQueue {\n\n  #heap = []\n  #compare;\n\n  constructor(compare) {\n    this.#heap = [];\n    this.#compare = compare || ((a, b) => a - b) //By default, keep it MinHeap\n  }\n\n  // Add a new element to the priority queue\n  enqueue = (value) => {\n    this.#heap.push(value);\n    this.#heapifyUp(this.#heap.length - 1);\n  }\n\n  // Remove and return the element with the highest priority (smallest for min-heap, largest for max-heap)\n  dequeue = () => {\n    if (this.#heap.length === 0) return null;\n    const root = this.#heap[0];\n    const end = this.#heap.pop();\n    if (this.#heap.length > 0) {\n      this.#heap[0] = end;\n      this.#heapifyDown(0);\n    }\n    return root;\n  }\n\n  // Peek at the element with the highest priority without removing it\n  peek = () => {\n    return this.#heap.length > 0 ? this.#heap[0] : null;\n  }\n\n  // Check if the priority queue is empty\n  isEmpty = () => {\n    return this.#heap.length === 0;\n  }\n\n  // Get the size of the priority queue\n  size = () => {\n    return this.#heap.length;\n  }\n\n  // Get the heap\n  get heap() {\n    return this.#heap\n  }\n\n  // Maintain heap property by moving element up\n  #heapifyUp = (index) => {\n    let parent = Math.floor((index - 1) / 2);\n    while (index > 0 && this.#compare(this.#heap[index], this.#heap[parent]) < 0) {\n      this.#swap(index, parent)\n      index = parent;\n      parent = Math.floor((index - 1) / 2);\n    }\n  }\n\n  // Maintain heap property by moving element down\n  #heapifyDown = (index) => {\n    const length = this.#heap.length;\n    let left = 2 * index + 1;\n    let right = 2 * index + 2;\n    let extreme = index;\n\n    if (left < length && this.#compare(this.#heap[left], this.#heap[extreme]) < 0) {\n      extreme = left;\n    }\n\n    if (right < length && this.#compare(this.#heap[right], this.#heap[extreme]) < 0) {\n      extreme = right;\n    }\n\n    if (extreme !== index) {\n      this.#swap(index, extreme)\n      this.#heapifyDown(extreme);\n    }\n  }\n\n  #swap = (i, j) => {\n    [this.#heap[i], this.#heap[j]] = [this.#heap[j], this.#heap[i]]\n  }\n}\n\n/**\n * @param {number[][]} grid\n * @param {number} health\n * @return {boolean}\n */\nfunction findSafeWalk(grid, health) {\n  const m = grid.length, n = grid[0].length;\n  const cnt = Array.from({ length: m }, () => Array(n).fill(0));\n  const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]];\n\n  const pq = new MinMaxPriorityQueue((a, b) => a[0] - b[0]);\n  pq.enqueue([health - grid[0][0], 0, 0]);\n\n  while (!pq.isEmpty()) {\n    const [h, i, j] = pq.dequeue();\n\n    if (i === m - 1 && j === n - 1) return true;\n\n    for (const [dx, dy] of directions) {\n      const x = i + dx, y = j + dy;\n      if (x >= 0 && y >= 0 && x < m && y < n && cnt[x][y] < h - grid[x][y]) {\n        cnt[x][y] = h - grid[x][y];\n        pq.enqueue([h - grid[x][y], x, y]);\n      }\n    }\n  }\n  return false;\n}\n```
['Array', 'Breadth-First Search', 'Graph', 'Heap (Priority Queue)', 'Matrix', 'Shortest Path', 'JavaScript']