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

LeetCode 2585: Number of Ways to Earn Points

·1 分鐘· ·
LeetCode Hard Dynamic-Programming Knapsack Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-08-27

  • 提交紀錄:Accepted ×2

解題思路
#

同一種題目的題目沒有差別,所以每種題目要決定的是選幾題(0 到 count)。這是有數量上限的背包,也可以看成分組背包:每一組(每一種題目)選一個選項。

dp[s] = 拿到剛好 s 分的方法數,dp[0] = 1。對每一種題目,容量倒著走,對每個 s 加上「這種選 k 題」的方法:dp[s] += dp[s - k × marks]。

倒著走保證 dp[s - k × marks] 還是上一種題目處理完的值,同一種題目不會被重複計算。

我的解法
#

class Solution:
    def waysToReachTarget(self, target: int, types: List[List[int]]) -> int:
        MOD = 10 ** 9 + 7
        dp = [1] + [0] * target                    # dp[s]:剛好 s 分的方法數
        for count, marks in types:
            for s in range(target, 0, -1):         # 倒著走
                for k in range(1, count + 1):      # 這種題目選 k 題
                    if s - k * marks < 0:
                        break
                    dp[s] = (dp[s] + dp[s - k * marks]) % MOD
        return dp[target]

s - k × marks 變成負的就可以 break,後面的 k 更大。

複雜度
#

時間 O(target · Σ count),空間 O(target)。

要特別避免的錯誤
#

  • 容量正著走:會變成同一種題目可以無限選。
  • 把同種的題目當成不同的:題目說它們沒有差別,所以只看選幾題。

面試口說整理
#

同一種題目沒有差別,所以每種題目只決定選幾題,從 0 到 count。這是有數量上限的背包,我用一維 dp,每種題目把容量倒著走,在裡面枚舉選幾題,把對應的方法數加上來。倒著走保證同一種題目不會被重複使用。時間 O(target · Σ count)。

相關文章

LeetCode 410: Split Array Largest Sum
·1 分鐘
LeetCode Hard Dynamic-Programming Binary-Search Greedy Prefix-Sum Array
LeetCode 410 解題筆記:對答案二分搜尋;給定上限 mid,貪心地能塞就塞,數出最少要切幾段,段數 <= k 就表示 mid 可行
LeetCode 2355: Maximum Number of Books You Can Take
·2 分鐘
LeetCode Hard Dynamic-Programming Monotonic-Stack Stack Array
LeetCode 2355 解題筆記:以 i 結尾時往左每格少拿 1 本,直到碰到書比較少的瓶頸書架 j;用單調堆疊找 j,dp[i] = dp[j] + 等差數列和
LeetCode 3989: Maximum Consistent Columns in a Grid
·1 分鐘
LeetCode Hard Dynamic-Programming Matrix Array
LeetCode 3989 解題筆記:保留的欄位是一個子序列,只要相鄰的兩欄相容;LIS 型 DP,dp[j] = 以第 j 欄結尾的最長合法序列
LeetCode 1402: Reducing Dishes
·1 分鐘
LeetCode Hard Dynamic-Programming Greedy Sorting Array
LeetCode 1402 解題筆記:排序後從滿意度大的開始選;每多選一道放在最前面,前面選的都往後一格,總和增加「目前選的滿意度總和」,總和是正的就繼續選
LeetCode 1526: Minimum Number of Increments on Subarrays to Form a Target Array
·1 分鐘
LeetCode Hard Dynamic-Programming Greedy Monotonic-Stack Array
LeetCode 1526 解題筆記:從左往右看,每次比前一個高,多出來的高度都要新開那麼多次操作;變矮的部分可以沿用之前的操作
LeetCode 3651: Minimum Cost Path with Teleportations
·2 分鐘
LeetCode Hard Dynamic-Programming Grid-Dp Matrix Array
LeetCode 3651 解題筆記:一層一層算傳送次數;傳送到某格的成本是上一層「值 >= 它的格子」的最小值,排序後用前綴最小值求,再跑一次右 / 下的 Grid DP