1. 程式人生 > 遊戲 >Suda51暗示《英雄不再3》或為系列最後一部作品

Suda51暗示《英雄不再3》或為系列最後一部作品

目錄

動態規劃總結

動態規劃中每一個狀態一定是由上一個狀態推匯出來的

明確兩個點,狀態和選擇

解題步驟

1.確定dp陣列以及下標的含義
2.確定遞推公式
3.dp陣列如何初始化
4.確定遍歷順序
5.舉例推導dp陣列

有一些情況遞推公式決定了dp陣列要如何初始化,所以先確定遞推公式。

如何debug

最好辦法是把dp陣列打印出來,觀察是否與解題步驟5所示自己推導的陣列一樣。
如果一樣,那麼就是遞推公式、初始化或者遍歷順序有問題。
如果不一樣,就是程式碼實現細節有問題。

揹包問題

重點是01揹包與完全揹包

01揹包

01揹包

滾動陣列

有N件物品和一個最多能放重量為W 的揹包。第i件物品的重量是weight[i],得到的價值是value[i] 。每件物品只能用一次,求解將哪些物品裝入揹包裡物品價值總和最大。

初始化陣列

倒敘遍歷,保證物品0只被放入一次

/*
dp[0][j],存放編號0的物品的時候,各個容量的揹包所能存放的最大價值。
這裡將的是0號物品,就不用考慮dp[i - 1][j],
*/
// 倒敘遍歷
for (int j = bagWeight; j >= weight[0]; j--) {
    dp[0][j] = dp[0][j - weight[0]] + value[0]; // 初始化i為0時候的情況
}

//感覺這裡可以直接初始化
for (int j = weight[0]; j >= weight[0]; j++) {
    dp[0][j] = value[0]; // 初始化i為0時候的情況
}

遍歷順序
有兩個遍歷維度:物品與揹包重量
先遍歷物品

  for(int i = 1; i < weight.size(); i++) { // 遍歷物品
        for(int j = 0; j <= bagWeight; j++) { // 遍歷揹包容量
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

        }
    }

一維寫法

void test_1_wei_bag_problem() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagWeight = 4;

    // 初始化
    vector<int> dp(bagWeight + 1, 0);
    for(int i = 0; i < weight.size(); i++) { // 遍歷物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍歷揹包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }
    cout << dp[bagWeight] << endl;
}

int main() {
    test_1_wei_bag_problem();
}