我在代码随想录|写代码Day35 | 动态规划| 01背包理论基础, 分割等和子集, 最后一块石头的重量II, 目标和
🔥博客介绍`: 27dCnc
🎥系列专栏: <<数据结构与算法>> << 算法入门>> << C++项目>>
🎥 当前专栏: <<数据结构与算法>>
专题 : 数据结构帮助小白快速入门算法
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆
❤️感谢大家点赞👍收藏⭐评论✍️
学习目标:
今日学习打卡
- 代码随想录 - 动态规划
学习时间:
- 周一至周五晚上 7 点—晚上9点
- 周六上午 9 点-上午 11 点
- 周日下午 3 点-下午 6 点
学习内容:
- 01背包理论基础
- 分割等和子集
- 最后一块石头的重量II
- 目标和
内容详细:
01背包理论基础
背包问题,也称背包问题,是经典的动态规划问题。
按照我个人理解: 01背包是有限的空间存放最大的价值, 有限的物品与,空间一定的背包,考察动态规划的转移过程,往往这种题目是要从最小的情况推到当前的情况
例题: 01背包问题
有 N N N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。
第 i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi 。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N行,每行两个整数 v i , w i v_i,w_i vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0 < N 0 < N 0<N, V ≤ 1000 V≤1000 V≤1000
0 < v i 0 < v_i 0<vi, w i ≤ 1000 w_i ≤ 1000 wi≤1000
样例输入
4 5
1 2
2 4
3 4
4 5
输出样例:
8
代码
#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
ll dp[1001][1001];
void solve() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
int w, v;
std::cin >> w >> v;
for (int j = 0; j <= t; j++) {
if (j >= w) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w] + v);
else dp[i][j] = dp[i - 1][j];
}
}
cout << dp[n][t] << endl;
}
int main(){
int T = 1;
for (int i = 1; i <= T; i++) solve();
}
分割等和子集
考点: 动态规划
代码
class Solution {
public:
bool canPartition(vector<int>& nums) {
int target = 0;
for (auto i : nums) {
target += i;
}
//不能将数据分为俩半,说明无法找到使得两个子集的元素和相等。
if (target % 2 == 1) return false;
target/=2;
//确定dp数组涵义
int dp[2*target];
//初始化dp数组
memset(dp,0,sizeof dp);
//dp数组遍历
for (int i = 1; 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;
}
};
最后一块石头的重量II
考点: 动态规划
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int n = stones.size();
int sum = 0;
sort(stones.begin(),stones.end());
vector<int>dp(15001,0);
for (auto& x : stones) {
sum += x;
}
int ans = sum;
sum /= 2;
for (int i = 0; i < stones.size(); i++) {
for (int j = sum;j >= stones[i]; j--) {
dp[j] = max(dp[j],dp[j - stones[i]] + stones[i]);
}
}
return ans - dp[sum] - dp[sum];
}
};
目标和
考点: 动态规划
思考
如何转化为01背包问题呢。
假设加法的总和为x,那么减法对应的总和就是sum - x。
所以我们要求的是 x - (sum - x) = target
x = (target + sum) / 2
此时问题就转化为,装满容量为x的背包,有几种方法。
这里的x,就是bagSize,也就是我们后面要求的背包容量。
大家看到(target + sum) / 2 应该担心计算的过程中向下取整有没有影响。
这么担心就对了,例如sum 是5,S是2的话其实就是无解的
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int n = stones.size();
int sum = 0;
sort(stones.begin(),stones.end());
vector<int>dp(15001,0);
for (auto& x : stones) {
sum += x;
}
int ans = sum;
sum /= 2;
for (int i = 0; i < stones.size(); i++) {
for (int j = sum;j >= stones[i]; j--) {
dp[j] = max(dp[j],dp[j - stones[i]] + stones[i]);
}
}
return ans - dp[sum] - dp[sum];
}
};
学习产出:
- 技术笔记 2 遍
- CSDN 技术博客 3 篇
- 习的 vlog 视频 1 个
重磅消息
算法交流群建立成功, 如果对算法感兴趣可以加入QQ群领取算法资料进行交流: 787936200
本文作者:2c237c6
本文链接:https://www.cnblogs.com/27dCnc/p/18568602
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步