背包相关
背包问题的总结,包含了基本背包,完全背包,多重背包,以及各问题的线性空间复杂度/二维空间复杂度解法。acwing有一些比较基础的题可以进行相关测试。
基本背包问题
01背包平方空间复杂度
int pack_01_vn(const vector<int> &costs, const vector<int> &values, int maxCost){
vector<vector<int>> dp(costs.size()+1,vector<int>(maxCost+1,0));
for (int i = 1; i <= costs.size(); ++i) {
int objidx = i-1;
for (int j = maxCost; j >= 0; j--) {
if(j >= costs[objidx]){
dp[i][j]=max(dp[i-1][j-costs[objidx]]+values[objidx],dp[i-1][j]);
}else{
dp[i][j]= dp[i-1][j];
}
}
}
return dp.back().back();
}
01背包线性空间复杂度
int pack_01_v(const vector<int> &costs, const vector<int> &values, int maxCost){
vector<int> dp(maxCost+1,0);
int nType = costs.size();
for (int i = 0; i < nType; ++i) {
for (int j = maxCost; j >= costs[i]; j--) {
dp[j] = max(dp[j],dp[j-costs[i]]+values[i]);
}
}
return dp[maxCost];
}
完全背包
完全背包平方空间复杂度
int pack_comp_vn(const vector<int> &costs, const vector<int> &values, int maxCost){
vector<vector<int>> dp(costs.size()+2,vector<int>(maxCost+1,0));
for (int i = 1; i <= costs.size()+1; ++i) {
int costi = i-2>=0?costs[i-2]:0;
int valuei = i-2>=0?values[i-2]:0;
for (int j = 0; j <= maxCost; j++) {
if(j >= costi){
dp[i][j]=max(dp[i][j-costi]+valuei,dp[i-1][j]);
}else{
dp[i][j]= dp[i-1][j];
}
}
}
return dp.back().back();
}
完全背包线性空间复杂度
int pack_comp_v(const vector<int> &costs, const vector<int> &values, int maxCost){
vector<int> dp(maxCost+1,0);
int nType = costs.size();
for (int i = 0; i < nType; ++i) {
int costi = i-1>=0?costs[i-1]:0;
int valuei = i-1>=0?values[i-1]:0;
for (int j = 0; j <= maxCost; j++) {
if(j - costi >= 0)
dp[j] = max(dp[j],dp[j-costi]+valuei);
}
}
return dp[maxCost];
}
多重背包
多重背包线性空间复杂度——二进制拆分
int pack_multi_v_bin(const vector<int> &costs, const vector<int> &values, const vector<int> &numbers, int maxCost){
vector<int> dp(maxCost+1,0);
int nType = costs.size();
for (int i = 0; i < nType; ++i) {
int base = 1;
int goodsLeft = numbers[i];
while(goodsLeft > 0){
int currN = base;
if(currN > goodsLeft)
currN = goodsLeft;
int currCost = currN*costs[i];
int currValue = currN*values[i];
for (int j = maxCost; j >= currCost; j--) {
dp[j] = max(dp[j],dp[j-currCost]+currValue);
}
goodsLeft -= currN;
base *= 2;
}
}
return dp[maxCost];
}
多重背包线性空间复杂度——单调队列
int pack_multi_v_queue(const vector<int> &costs, const vector<int> &values, const vector<int> &nums,int maxCost){
vector<int> dp_prev(maxCost+1,0);
vector<int> monotone_queue(maxCost+1,0);
vector<int> dp(maxCost+1,0);
for (int i = 0; i < costs.size(); ++i) {
dp_prev=dp;
int volume=costs[i], value = values[i], number=nums[i];
for (int j = 0; j < volume; ++j) {
int head = 0, tail = -1;
for (int k = j; k <= maxCost; k += volume) {
if (head <= tail && (k - monotone_queue[head]) / volume > number)
head++;
if (head <= tail)
dp[k] = max(dp[k], dp_prev[monotone_queue[head]] + (k - monotone_queue[head]) / volume * value);
while (head <= tail && dp_prev[monotone_queue[tail]] - (monotone_queue[tail] - j) / volume * value<= dp_prev[k] - (k - j) / volume * value) {
--tail;
}
monotone_queue[++tail] = k;
}
}
}
return dp[maxCost];
}