代码随想录算法训练营第四十二天 | 1049最后一块石头的重量II 494.目标和 474.一和零
1049.最后一块石头的重量
解题思路:
将石头尽量分为相等的两堆,两堆最差即为所求结果
石头的重量就是石头的价值
动规五部曲:
- dp[j]:表示背包容量为j时可以装的石头的总价值
- 递推公式:dp[j] = max(dp[j], dp[j-stones[i]] + stones[i]
- 初始化:均初始化为0
- 遍历顺序:先遍历石头后遍历背包
- 打印dp数组
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int weight = 0;
for(int val : stones) weight += val;
int capcity = weight / 2;
// dp[j] 表示容量为j的背包装的石头的总价值最大为多少
vector<int> dp(capcity + 1);
for(int j = 0; j <= capcity; ++j) dp[j] = 0;
// 递推公式: dp[j] = max(dp[j], dp[j-weight[i]] + value[i])
// 初始化:均初始化为0
for(int j = 0; j < capcity; ++j) dp[j] = 0;
// 先遍历石头后遍历背包
for(int i = 0; i < stones.size(); ++i) {
for(int j = capcity; j >= stones[i]; --j) {
dp[j] = max(dp[j], dp[j-stones[i]] + stones[i]);
}
}
return weight - (dp[capcity] << 1);
}
};
494.目标和
思路:将数组分为两个集合left全部存整数,target全部存负数
那么满足:left + right = sum; left - right = target;
计算得left = (sum + target) / 2;
left即为背包的容量
动规五部曲:
- dp[j]:装满容量为j的背包有dp[j]种方法
- 递推公式:dp[j] += dp[j - nums[i]]
- 初始化:dp[0] = 1, 其他初始化为0
- 遍历顺序:先遍历物品后遍历背包,背包倒序遍历
- 打印dp数组
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum = 0;
for(int val : nums) sum += val;
if((sum + target) % 2 == 1) return 0;
if(abs(target) > sum) return 0;
int left = (sum + target) >> 1;
// dp[j]: 表示容量为j的背包装哪些数可以正好装满
vector<int> dp(left + 1, 0);
// 递推公式: dp[j] = dp[j], dp[j - nums[i]] + nums[i];
// 初始化
dp[0] = 1;
for(int i = 0; i < nums.size(); ++i) {
for(int j = left; j >= nums[i]; --j) {
dp[j] += dp[j - nums[i]];
}
}
for(int val : dp) cout << val << " ";
return dp[left];
}
};
474.一和零
- dp[i][j]: 表示装满i个0和j个1最多可以装dp[i][j]个物品
- 递推公式:dp[i][j] = max(dp[i - x][j - y], dp[i][j])
- 初始化:均初始化为0
- 遍历顺序:先遍历物品后遍历背包
- 打印dp数组
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
// dp[i][j]: 装满i个0和j个1,最多装多少个
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
// 递推公式: dp[i][j] = max(dp[i - x][j - y] + 1, dp[i][j])
// 初始化 dp[i][j] = 0
// 遍历顺序,先遍历物品后遍历背包
for(string str : strs) {
int x = 0, y = 0;
for(char ch : str) {
if(ch == '0') ++x;
else ++y;
}
// 遍历背包
for(int i = m; i >= x; --i) {
for(int j = n; j >= y; --j) dp[i][j] = max(dp[i - x][j - y] + 1, dp[i][j]);
}
}
return dp[m][n];
}
};
分类:
代码随想录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构