提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
今天是跟着代码随想录刷题的第42天,主要学了最后一块石头的重量2、目标和和一和零三个问题
提示:以下是本篇文章正文内容,下面案例可供参考
一、最后一块石头的重量2
思路:和0-1背包差不多,主要就是以一个二分之一的背包容量,看最多能放多少,能放离这个二分之一背包越近越好,然后就是让结果减去两个这个就是最终的答案。
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
vector<int> dp(15001, 0);
int sum = 0;
for (int i = 0; i < stones.size(); i++) sum += stones[i];
int target = sum / 2;
for (int i = 0; i < stones.size(); i++) { // 遍历物品
for (int j = target; j >= stones[i]; j--) { // 遍历背包
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
return sum - dp[target] - dp[target];
}
};
二、目标和
思路:
假设加法的总和为x,那么减法对应的总和就是sum - x。
所以我们要求的是 x - (sum - x) = target
x = (target + sum) / 2
核心思路就是dp【i】表示有多少种方法能够装满这个容量为5的背包,然后dp【5】等于啥呢,等于上一个dp【5】(也就是没有放这一层东西的)加上上一层的dp【5-nums【5】】(就是上一层把这个新加的东西预留出来,这样这一层可以放这个东西)
还需要考虑dp【0】是什么的问题, dp【0】就是我从有一个东西的里面取,取的和为0有几种情况,很明显就一种,我直接不取就可以了,所以就是一种。
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) sum += nums[i];
if (abs(S) > sum) return 0; // 此时没有方案
if ((S + sum) % 2 == 1) return 0; // 此时没有方案
int bagSize = (S + sum) / 2;
vector<int> dp(bagSize + 1, 0);
dp[0] = 1;
for (int i = 0; i < nums.size(); i++) {
for (int j = bagSize; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[bagSize];
}
};
三、一和零
思路:
这道题就是一个二维的背包,第一个for循环就是遍历物品
第二个第三个for循环都是遍历背包,所以要注意第二个第三个的for循环一定要注意倒序才行
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m+1,vector<int> (n+1,0));
for(string str:strs)
{
int zeronum=0;
int onenum=0;
for(char c:str)
{
if(c=='0') zeronum++;
else onenum++;
}
for(int i=m;i>=zeronum;i--)
{
for(int j=n;j>=onenum;j--)
{
dp[i][j]=max(dp[i][j],dp[i-zeronum][j-onenum]+1);
}
}
}
return dp[m][n];//我很想你
}
};