↓快轉到主要內容
  1. LeetCode/

LeetCode 2912: Number of Ways to Reach Destination in the Grid

·2 分鐘· ·
LeetCode Hard Dynamic-Programming State-Machine Math Combinatorics
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-07-30

  • 提交紀錄:Wrong Answer → Accepted ×2

解題思路
#

每一步可以移到同一列或同一行的任何其他格子。格子有 n × m 個,但相對於終點 (dx, dy) 只有四類,同一類的格子行為完全一樣:

類別條件格子數
0就是終點1
1x == dx、y != dy(同一列)m - 1
2x != dx、y == dy(同一行)n - 1
3都不同其他

dp[c] = 走到類別 c 裡所有格子的方法數總和。從一個格子出發能到哪幾類:

  • 從終點:同一列的 m - 1 格(類別 1)、同一行的 n - 1 格(類別 2)。
  • 從類別 1 的格子 (dx, y):終點 1 格、類別 1 的其他 m - 2 格、同一行的 n - 1 格都在類別 3。
  • 從類別 2:對稱。
  • 從類別 3 的格子 (x, y):(dx, y) 是類別 1、(x, dy) 是類別 2,其他 n + m - 4 格都是類別 3。
new0 = dp1 + dp2
new1 = (m - 1) dp0 + (m - 2) dp1 + dp3
new2 = (n - 1) dp0 + (n - 2) dp2 + dp3
new3 = (n - 1) dp1 + (m - 1) dp2 + (n + m - 4) dp3

我的嘗試
#

第一版的轉移把兩種意義混在一起:有的係數是用「某一個特定格子的方法數」推的,有的是用「整類的總和」推的,結果係數放錯位置。例如 n = 2、m = 4、k = 2、從 [2, 4] 走到 [1, 1]:答案是 2(經過 [2, 1] 或 [1, 4]),回傳 6。

統一成「dp[c] 是整類的總和」,每個係數都從「這類的一個格子能到哪幾類、各幾格」推,就對了。

正確解法
#

class Solution:
    def numberOfWays(self, n: int, m: int, k: int, source: List[int], dest: List[int]) -> int:
        MOD = 10 ** 9 + 7
        sx, sy = source
        dx, dy = dest
        dp = [0, 0, 0, 0]                          # 四類各自的總方法數
        if (sx, sy) == (dx, dy):
            dp[0] = 1
        elif sx == dx:
            dp[1] = 1
        elif sy == dy:
            dp[2] = 1
        else:
            dp[3] = 1

        for _ in range(k):
            d0, d1, d2, d3 = dp
            dp = [
                (d1 + d2) % MOD,
                ((m - 1) * d0 + (m - 2) * d1 + d3) % MOD,
                ((n - 1) * d0 + (n - 2) * d2 + d3) % MOD,
                ((n - 1) * d1 + (m - 1) * d2 + (n + m - 4) * d3) % MOD,
            ]
        return dp[0]

複雜度
#

時間 O(k),空間 O(1)。(4 × 4 的轉移矩陣也可以用快速冪做到 O(log k)。)

要特別避免的錯誤
#

  • dp 的意義要統一:整類的總和,不是一個格子的方法數。
  • 不能停在原地,所以同一類的轉移是 m - 2、n - 2,不是 m - 1、n - 1。

面試口說整理
#

格子很多,但相對終點只分四類,同一類的格子行為一樣。我讓 dp 存每一類所有格子的方法數總和,從一類的一個格子出發,數它能到每一類的幾個格子,就是轉移係數。走 k 步之後回傳終點那類。時間 O(k)。

相關文章

LeetCode 60: Permutation Sequence
·1 分鐘
LeetCode Hard Math Combinatorics Recursion
LeetCode 60 解題筆記:k 改成 0-indexed,第一位決定之後剩下 (n-1)! 種排法;k // (n-1)! 就是第一位在剩下的數字裡排第幾,取出後繼續處理下一位
LeetCode 1411: Number of Ways to Paint N × 3 Grid
·1 分鐘
LeetCode Hard Dynamic-Programming State-Machine Graph-Coloring
LeetCode 1411 解題筆記:一列的塗法只分兩種樣式:ABA(兩端同色)和 ABC(三色不同),各 6 種;下一列 ABA → 3 ABA + 2 ABC、ABC → 2 ABA + 2 ABC
LeetCode 3518: Smallest Palindromic Rearrangement II
·2 分鐘
LeetCode Hard Math Combinatorics Counting Hash-Table String
LeetCode 3518 解題筆記:回文由左半邊決定,變成「多重集合的第 k 個排列」;逐位試每個字元,用排列數判斷第 k 個落在哪個分支,排列數可以 O(1) 更新
LeetCode 902: Numbers At Most N Given Digit Set
·1 分鐘
LeetCode Hard Dynamic-Programming Digit-Dp Math Binary-Search String
LeetCode 902 解題筆記:數位 DP,狀態是 (pos, tight, started);還沒開始時可以跳過這一位,代表位數比 n 少的數
LeetCode 552: Student Attendance Record II
·2 分鐘
LeetCode Hard Dynamic-Programming State-Machine
LeetCode 552 解題筆記:狀態機 DP,狀態是「A 用了幾次 × 結尾連續幾個 L」共 6 種;每天選 P、A、L 決定下一個狀態
LeetCode 123: Best Time to Buy and Sell Stock III
·3 分鐘
LeetCode Hard Dynamic-Programming State-Machine
LeetCode 123 解題筆記,依照原始 learning note 重新整理