卡码网46. 携带研究材料
#include<bits/stdc++.h>
using namespace std;
int n,bagweight;
void solve()
{
vector<int>weight(n,0);
vector<int>value(n,0);
for(int i=0;i<n;++i)
{
cin>>weight[i];
}
for(int j=0;j<n;++j)
{
cin>>value[j];
}
vector<vector<int>>dp(weight.size(),vector<int>(bagweight+1,0));
for(int j=weight[0];j<=bagweight;j++)
{
dp[0][j]=value[0];
}
for(int i=1;i<weight.size();i++)
{
for(int j=0;j<=bagweight;j++)
{
if(j<weight[i]) dp[i][j]=dp[i-1][j];
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
}
}
std::cout << dp[weight.size()-1][bagweight] << std::endl;
}
int main()
{
while(cin>>n>>bagweight)
{
solve();
}
return 0;
}
void test_1_wei_bag_problem() {
vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30};
int bagWeight = 4;
// 初始化
vector<int> dp(bagWeight + 1, 0);
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[bagWeight] << endl;
}
int main() {
test_1_wei_bag_problem();
}
416. 分割等和子集
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = 0;
// dp[i]中的i表示背包内总和
// 题目中说:每个数组中的元素不会超过 100,数组的大小不会超过 200
// 总和不会大于20000,背包最大只需要其中一半,所以10001大小就可以了
vector<int> dp(10001, 0);
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
}
// 也可以使用库函数一步求和
// int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum % 2 == 1) return false;
int target = sum / 2;
// 开始 01背包
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]);
}
}
// 集合中的元素正好可以凑成总和target
if (dp[target] == target) return true;
return false;
}
};