3

背包问题的核心公式

 2 years ago
source link: https://segmentfault.com/a/1190000041140486
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

背包问题的核心公式

把每个背包问题的核心代码放在一块,更好的区分不同问题的代码实现。当然,在实现代码之前,要先了解每个背包问题解决问题的思路。

物品的重量数组是 weight (int[]),价值数组是 value (int[]),背包容量是 bagWeight

1. 0-1 背包

从大到小遍历,为了保证每个物品仅被添加一次

1.1 使用二维数组存储

递推公式

dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
(dp[i][j]:放入物品和不放入物品,哪个值大)

dp 大小

int[weight.size()][bagWeight+1][物品个数][背包容量+1]

代码

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) {
    for(int j = bagWeight; j >= 0; 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])
    }
}

1.2 使用一维数组存储

递推公式

dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
( dp[j]:放入物品和不放入物品,哪个值大)

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历物品,再遍历背包
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]);
    }
}

2. 完全背包

完全背包的物品是可以添加多次的,所以要从小到大去遍历

2.1 组合

递推公式

dp[j] = max(dp[j], dp[j-nums[i]]) ( dp[j]:由 dp[1], dp[2], ... dp[j-1] 而来)

递推公式根据实际情况有所变化,通过找寻 dp[j] 是怎么通过其他的 dp 值推导而确定公式

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历物品,再遍历背包
for (int i = 0; i < weight.size(); i++) {
    for(int j = weight[i]; j < bagWeight ; j++) {
        dp[j] = max(dp[j], dp[j-weight[i]]+value[i])
    }
}

2.2 排列

递推公式

dp[j] = dp[j-nums[i]] ( dp[j]:由 dp[1], dp[2] ... dp[j-1] 而来)

递推公式根据实际情况有所变化,通过找寻 dp[j] 是怎么通过其他的 dp 值推导而确定公式

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历背包,再遍历物品
for(int j = 0; j <= bagWeight; j++) { 
    for(int i = 0; i < weight.size(); i++) { 
        if (j >= wieght[i]) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK