【Lintcode】python - [798] Backpack VII 個人解法筆記

題目出處

798 · Backpack VII

難度

medium

個人範例程式碼

from typing import (
    List,
)

class Solution:
    """
    @param n: the money of you
    @param prices: the price of rice[i]
    @param weight: the weight of rice[i]
    @param amounts: the amount of rice[i]
    @return: the maximum weight
    """
    def back_pack_v_i_i(self, n: int, prices: List[int], weight: List[int], amounts: List[int]) -> int:
        # write your code here
        m = len(prices)
        dp = [[0]*(n+1) for _ in range(2)] # rotated array
        num_of_selected_items = 0

        for i in range(m): # take one kind of price
            for get_j_amount in range(1, amounts[i]+1): # get j amount 
                num_of_selected_items += 1
                for current_price in range(prices[i], n+1): 
                    dp[num_of_selected_items%2][current_price] = dp[(num_of_selected_items-1)%2][current_price]
                    last_price = current_price - prices[i]
                    if last_price >= 0:
                        dp[num_of_selected_items%2][current_price] = max(dp[num_of_selected_items%2][current_price], dp[(num_of_selected_items-1)%2][last_price] + weight[i]) 
                # print(i, get_j_amount, dp)

        return dp[num_of_selected_items%2][-1]

算法說明

本題是背包系列問題的第 7 題,建議初學者可以從第一題開始去學:
第 1 題:最基本的背包問題,不重複 size,物品只有一個,計算組合可能性
第 2 題:最基本的背包問題,不重複 size,物品只有一個,計算最大價值
第 3 題:完全背包問題,有重複 size,物品無限數量,計算最大價值
第 4 題:有重複 size,物品無限數量,計算可能組合 ,「(1,2,3) 與 (2,3,1) 視為相同答案」
第 5 題:有重複 size,物品有限數量,計算可能組合 ,「(1,2,3) 與 (2,3,1) 視為相同答案」
第 6 題:有重複 size,物品無限數量,計算可能「排列」 ,也就是說「(1,2,3) 與 (2,3,1) 視為不同答案」
第 7 題:有重複物品,有限制物品數數量上限,問可能組合
第 8 題:有重複物品,有限制物品數數量上限,問最大價值
第 9 題:變化問題,有重複 size,計算機率
第 10 題:變化問題,只是把 size 面額提高

第七題,這題我們要處理的是有重複、但有限制使用上限數量的問題。
不同於只能使用一個,也不同於可以使用無線數量,
我們在搜尋時需要多加一個計數器,來幫助我們避免超過使用上限。

一種思維是 [2,4]*[3,1] 直接看做 [2,2,2,4] 來處理,也許會更容易 (就能夠比照單一數量的題目辦理)。

input handling

一同在 dp 內處理

Boundary conditions

用三層 for 來控制搜尋範圍,
外層 for 控制選擇種類,
內層 for 控制上限數量,
最內層 for 使用的金錢上限 (表示我們目前花了多少錢)

Reference