01背包问题 二维
思路
1.确定dp数组及下标含义:
dp[i][j]:表示从下标为0-i的物品里任意取,放进容量为j的背包,价值最大
2.确定递推公式:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
3.dp数组初始化:
当j<weight[0],dp[0][j]=0;当j>=weight[0],dp[0][j]=value[0]
dp[i][0]=0;
01背包问题 一维
思路
1.确定dp数组的含义:
dp[j]表示背包容量为j,最大价值为dp[j]
2.确定递推公式:
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]
3.初始化:
若物品价值>0,dp数组初始化为0
若物品价值为负,dp数组初始化为负无穷
4.确定遍历顺序:
外层遍历物品,内层遍历背包,且内层倒序遍历
倒序遍历是为了保证物品i只被遍历一次
5.举例推导dp数组
416. 分割等和子集 题目链接
思路
1.确定递推数组dp[j]及下标含义:
dp[j]表示背包容量为j,最大价值为dp[j]
2.确定递推公式:
dp[j]=max(dp[j],dp[j-nums[i]]+nums[i])
3.dp数组如何初始化:
廷尉题目要求“包含正整数”,将数组初始化为0
4.确定遍历顺序:
外层遍历物品,内层遍历背包,且内层是倒序遍历
5.距离推导dp数组
Code
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum=0;
vector<int>dp(10001,0);
for(int i=0;i<nums.size();i++)
{
sum+=nums[i];
}
if(sum%2==1)return false;
int target=sum/2;
for(int i=0;i<nums.size();i++)
{
for(int j=target;j>=nums[i];j--)
dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
}
if(dp[target]==target)return true;
else return false;
}
};
复杂度
时间复杂度:
O(n^2)
空间复杂度:
O(n)