背包问题本质
背包问题是【动态规划】中十分经典的一类问题,本质上属于组合优化的【NP完全问题】,是一个无法避免【穷举】的问题,同时也满足【无后效性】。
【背包问题】大概对应这样的一类问题:泛指一类【给定价值与成本】,同时【限定决策规则】,在这样的条件下,如何实现价值最大化的问题。
「01背包」是指给定物品价值与体积(对应了「给定价值与成本」),在规定容量下(对应了「限定决策规则」)如何使得所选物品的总价值最大。
题目描述
有N件物品和一个容量为V的背包,每件物品有且只有1件。第i件物品的题只为v[i],价值为w[i],求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
解法:动态规划,dp[N][C+1]
- dp数组定义:dp[i][j]:枚举到第i件物品时,剩余容量为j,此时能获得的最大价值
- 不失一般性的,我们只需要考虑第 i件物品如何选择即可,对于第 i件物品,我们有「选」和「不选」两种决策。「不选」其实就是 ,等效于我们只考虑前i-1件物品,当前容量为 j的情况下的最大价值。同理,如果我们选第i件物品的话,代表消耗了v[i]的背包容量,获取了w[i]的价值,那么留给前i-1件物品的背包容量就只剩j-v[i] 。即最大价值为dp[i-1][j-v[i]] + w[i]。当然,选第i件有一个前提:「当前剩余的背包容量」>=「物品的体积」。
- 状态转移方程:dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]]+w[i])
class Solution {//物品编号从0开始,到N-1一共N件,体积从0到C一共C+1个选择public int maxValue(int N, int C, int[] v, int w) {int[][] dp = new int[N][C+1]; //res = dp[N-1][C]//base case,第一件物品for (int i=0; i<=C; i++) {dp[0][i] = i >= v[0] ? w[0] : 0;}//剩余物品for (int i=0; i<N; i++){for (int j=0; j<C+1; j++) {int noChoose = dp[i-1][j]; //int Choose = j >= v[i] ? dp[i-1][j-v[i]] + w[i] : 0;dp[i][j] = Math.max(noChoose, Choose);}}return dp[N-1][C];}}

优化
优化1:
优化2:
