0-1背包,一个物品有重量和价值两个属性;每个物品只能用一次,一般问在重量为j下能获得到的最大价值
dp[i][j]:表示可以在【0, i】范围内拿物品,重量不超过【j】的最大重量;
所以二维递推公式为:
dp[i][j] = max(dp[i-1][j] , dp[i - 1][j - weight[i]] + value[i])
压缩一维后:
dp[j] = max(dp[j] , dp[j- weight[i]] + value[i]) ;
原理:从后往前遍历j,因为此时用到的dp是上一层的dp;
具体写法:
for (int i = 0; i < nums.size(); i ++) {
for (int j = target; nums[i] <= j; j--){ //注意j要大于nums[i]
dp[j] = max(dp[j] , dp[j-nums[i]] + nums[i] ) ;
}
}
416. 分割等和子集
知识点:动规
状态:看答案
思路:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
for(int a : nums) sum += a;
if(sum %2 != 0) return false;
int target = sum / 2;
vector<int> dp(10001, 0);
for (int i = 0; i < nums.size(); i ++) {
for (int j = target; nums[i] <= j; j--){
dp[j] = max(dp[j] , dp[j-nums[i]] + nums[i] ) ;
}
}
if(dp[target] == target ) return true;
return false;
}
};