题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)
class Solution
{
public:
int lastStoneWeightII(vector<int> &stones)
{
vector<int> dp(15001,0);//题目给出,stones长度最大为30,单个重量最大为100,所以总重量为30000
//本体的解题思路就是通过01背包,尽量把重量分为想等的2组,然后一碰!重量相减就得出了剩下的大小
int sum=0;
for(int i=0;i<stones.size();i++){
sum+=stones[i];//计算总重量
}
int target=sum/2;//计算dp数组里面应该放的重量
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];
}
};
使用一维数组的方式做dp数组,即为滚动数组。也可以用二维数组,像之前一开始那样,不过一位更省空间。
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum=0;//数组能达到的最大总和,也就是全部都取整数进行相加
for(int i=0;i<nums.size();i++) sum+=nums[i];
if(sum<abs(target)) return 0;
if((sum+target)%2==1) return 0;//如果sum和target一个是奇数,一个是偶数,怎么调正负号都不能得出target
//假设正数为x,那么负数就为-(sum-x)。
//正数和负数相加就要等于target,即x+(-(sum-x))==target
//可以得到x==(sum+target)/2.
//用01背包解决的话,问题转化为装满大小为x的背包有多少种办法(这里只需要考虑正数x就行,负数的个数由正数个数决定)
int bagSize=(sum+target)/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];
}
};
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
for (string str : strs) { // 遍历物品
int oneNum = 0, zeroNum = 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];
}
};