LeetCode-- Daily – 动态规划 --背包问题
416.分割等和子集(0-1背包)
AC代码 1 (普通动态规划流程):
class Solution {
public:
bool canPartition1(vector<int>& nums) {
int n = nums.size(), sum_nums = accumulate(nums.begin(), nums.end(), 0);
if (sum_nums % 2) return false;
sum_nums = sum_nums / 2;
vector<vector<int>> dp(n+1 , vector<int>(sum_nums + 1, false));
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= sum_nums; j++) {
if (nums[i - 1] <= j)
dp[i][j] = dp[i-1][j] || dp[i - 1][j - nums[i-1]];
else dp[i][j] = dp[i-1][j];
//cout<<dp[i][j]<<" " ;
}
//cout << endl;
}
return dp[n][sum_nums];
}
};
AC代码 2 (压缩空间):
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size(), sum_nums = accumulate(nums.begin(), nums.end(), 0);
if (sum_nums % 2) return false;
sum_nums = sum_nums / 2;
vector<int> dp(sum_nums + 1, false);
dp[0] = true;
for (int i = 1; i <= n; i++) {
for (int j = sum_nums; nums[i - 1] <= j; j--) {
dp[j] = dp[j] || dp[j - nums[i-1]];
}
}
return dp[sum_nums];
}
};
解题思路总结:
1. ** dp矩阵的含义* *:dp[i][j]: num[0:i-1]是否能满足背包装下j的物品
2. **递推公式**:两种情况 -- 放入背包 和 不放入背包
    能放入背包: 放入num[i-1]前的dp值(即dp[i-1][j-nums[i]]) || num[0:i-2]是否能满足j的背包容量(dp[i-1][j])
    不能放入背包:num[0:i-2]是否能满足j的背包容量(dp[i-1][j])
3. **循环位置的确定**:为什么 j 从0开始:保证dp[ : ][0]都是True,因为dp向前回溯时会用到左上的值,如果想从1开始,可以在dp初始化时改变第一列的值。
4. **使用压缩空间的方法时**:相当于在构建dp矩阵时忽略物品的维度, 且循环顺序改为倒序(避免是重复放入),循环的停止条件直接选用循环内的截至条件,减少了代码量。
474.一和零(0-1背包)
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
int count1=0,count0=0;
for(const string &str :strs){
count0 =0,count1=0;
for(const char & c :str){
if (c=='1') count1++;
else count0++;
}
for(int i=m;i>=count0;i--){
for(int j=n;j>=count1;j--){
dp[i][j] = max(dp[i][j],1+dp[i-count0][j-count1]);
}
}
}
return dp[m][n];
}
};
解题思路总结:
0. 此题目有三个变量,之前一直是背包1维,物品一维,现在背包成了二维( m 个1以及 n 个0),如果普通的套路需要将dp矩阵初始化成三维,相对麻烦,因此将dp矩阵初始化为m*n的,相当于从3维数组压缩空间至2维数组。
1. dp的含义 :dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
2. 递推公式 :dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
加入物品前的dp状态+1 和 本身的状态取最大值
3. 物品1维,背包2维,如果要使用二维的dp,则需要压缩空间,将背包的size作为dp的大小,且初始化为0即可
4. 循环顺序:压缩空间则是倒序。