卡码网 46. 携带研究材料
题目链接:卡码网 46. 携带研究材料
题目描述: 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 N
,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。
输入描述:
第一行包含两个正整数,第一个整数 M
代表研究材料的种类,第二个正整数 N
,代表小明的行李空间。
第二行包含 M
个正整数,代表每种研究材料的所占空间。
第三行包含 M
个正整数,代表每种研究材料的价值。
输出描述: 输出一个整数,代表小明能够携带的研究材料的最大价值。
思路: 本题不同与以往的Leetcode题目,需要额外处理输入输出,不过本题是一道01背包模板题,还是比较简单的。(不了解01背包可以先看下面两个链接,着重注意优化前后的遍历顺序)
01背包理论基础
01背包理论基础(利用滚动数组优化)
代码如下:(动态规划)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5010;
int v[N],w[N],f[N][N];
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> v[i];
for(int i = 1; i <= n; i ++) cin >> w[i];
for(int i = 1; i <= n; i ++ )
for(int j = 0; j <= m; j ++ )
{
if(j >= v[i]) f[i][j] = max(f[i - 1][j] , f[i - 1][j - v[i]] + w[i]);
else f[i][j] = f[i - 1][j];
}
cout << f[n][m];
return 0;
}
代码如下:(动态规划+滚动数组优化)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5010;
int v[N],w[N],f[N];
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> v[i];
for(int i = 1; i <= n; i ++) cin >> w[i];
for(int i = 1; i <= n; i ++ )
for(int j = m; j >= 0; j -- )
{
if(j >= v[i]) f[j] = max(f[j] , f[j - v[i]] + w[i]);
}
cout << f[m];
return 0;
}
Leetcode 416. 分割等和子集
题目链接:Leetcode 416. 分割等和子集
题目描述: 给你一个只包含正整数的非空数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
思路: 本题可以用01背包解决,不过难点在于如何将本题转换成01背包问题。
- 题中需要让子集元素之和等于
target / 2
,因此可以将其看为背包容量。 - 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
- 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
- 背包中每一个元素是不可重复放入。
代码如下:
class Solution {
public:
bool canPartition(vector<int>& nums) {
vector<int> dp(10005, 0);
//计算数组元素总和的一半
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum & 1) //如果sum是奇数直接返回false
return false;
int target = sum / 2;
for (int i = 0; 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;
return false;
}
};
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)
总结: 01背包问题算是背包问题中的基础问题,理解其原理之后会对后续更复杂的背包问题更有帮助。
最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!