欢迎来到Cefler的博客😁
🕌博客主页:折纸花满衣
🏠个人专栏:题目解析
🌎推荐文章:【LeetCode】winter vacation training
👉🏻01背包
原题链接:01背包
mycode:
#include <iostream>
#include<vector>
using namespace std;
int main() {
int n,V;
cin>>n>>V;
vector<int> w(n+1),v(n+1);
// vector<vector<int>> goods(n,vector<int>(2));
for(int i = 1;i<=n;i++) cin>>v[i]>>w[i];
//创建dp表
vector<vector<int>> dp1(n+1,vector<int>(V+1)),dp2(n+1,vector<int>(V+1));
//dp表初始化
for(int i = 1;i<V+1;i++)
{
dp2[0][i] = -1;
}
//开始填表
for(int i = 1;i<n+1;i++)
{
for(int j = 1;j<V+1;j++)
{
//dp1[i][j]特征方程
dp1[i][j] = dp1[i-1][j];
if(j-v[i]>=0)
dp1[i][j] = max(dp1[i][j],w[i]+dp1[i-1][j-v[i]]);
//dp2[i][j]特征方程
dp2[i][j] = dp2[i-1][j];
if(j-v[i]>=0&&dp2[i-1][j-v[i]]!=-1)
dp2[i][j] = max(dp2[i][j],w[i]+dp2[i-1][j-v[i]]);
}
}
cout<<dp1[n][V]<<endl;
cout<<(dp2[n][V]==-1?0:dp2[n][V])<<endl;
}
👉🏻分割等和子集
原题链接:分割等和子集
mycode1(超出内存限制):
class Solution {
public:
vector<vector<int>> subset;
vector<int> part;
void dfs(vector<int>& nums,int n)
{
//可以选择插入或选择不插入
for(int i = n;i<nums.size();i++)
{
part.push_back(nums[i]);
dfs(nums,i+1);
//回溯清理现场
part.pop_back();
}
subset.push_back(part);
}
bool canPartition(vector<int>& nums) {
//找到满足元素数<=n-1,和等于总和一半的子集
//dp[i][j]:表示i个元素
//先求和
int Sum = 0;
int n = nums.size();
for(int i = 0;i<n;i++) Sum+=nums[i];
if(Sum%2!=0) return false;
dfs(nums,0);
for(int i = 0;i<subset.size();i++)
{
if(std::accumulate(subset[i].begin(),subset[i].end(),0)==(Sum/2))
return true;
}
return false;
}
};
mycode2:
class Solution {
public:
bool canPartition(vector<int>& nums) {
int Sum = std::accumulate(nums.begin(),nums.end(),0);
if(Sum%2!=0) return false;
int n = nums.size(),halfSum = Sum/2;
//创建dp表
vector<vector<bool>> dp(n+1,vector<bool>(halfSum+1));
//dp表初始化
for(int i = 0;i<n+1;i++) dp[i][0] = true;
//开始填表
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=halfSum;j++)
{
dp[i][j] = dp[i-1][j];//不选i位置元素
//选择i位置元素
if(j-nums[i-1]>=0)
dp[i][j] = dp[i][j] || dp[i-1][j-nums[i-1]];
}
}
return dp[n][halfSum];
}
};