格式化的代码求解背包问题
先验: 《背包九讲》的pdf先熟悉一波
416.选择子集和等于所有元素值和的一半
转化: 0-1背包恰好装满问题
/*
0-1背包的恰好装满的问题
选择若干物品,使得物品价值和 恰好等于sum(array)/2
背包容量: sum(array)/2
重量花费cost: array[i]
物品价值: 0 本题: 也可以将"价值"设定为array[i]
恰好装满: dp[0]=0, dp[1,...V]=INT_MIN
*/
#include "func.h"
int V = 0; //背包体积
void zeroOnePack(vector<int>&F,int costi, int weighti){
for(int i=V;i>=costi;i--) //3. >=,逆序
F[i] = std::max(F[i],F[i-costi]+weighti);
}
bool canPartition(vector<int>& array){
int sum = 0;
for(auto& i : array) sum += i;
if(sum%2) return false;
V = sum/2;
vector<int> F(V+1,INT32_MIN); //0.init V+1空间长度
F[0] = 0;
for(int i=0;i<array.size();i++) //遍历每一件物品
zeroOnePack(F,array[i],0); //1.zeroOnePack
if(F.back() == INT32_MIN) return false;
else return true;
}
.
.
1049.两两的取石头,碰撞后减去小的重量,最后1块石头时的"最小"重量
转化: 0-1背包不超过背包体积下的最大重量
/*
两两的取石头,碰撞后减去小的重量,最后1块石头时的"最小"重量
转化0-1背包:
背包体积: sum(array)/2
重量费用:array[i]
价值:array[i] 本题:设定最大化的目标=重量
不超过背包容量,计算石头能占据的最大"价值"
F[0,...V] = 0
*/
#include "func.h"
// 0-1背包遍历物品个数&体积容量
int V = 0;
void zeroOnePack(vector<int>&F,int costi,int valuesi){
for(int i=V;i>=costi;i--)
F[i] = std::max(F[i],F[i-costi]+valuesi);
}
int lastStoneWeightII(vector<int>& array){
int sum = 0;
for(auto& i : array) sum+=i;
V = (int)sum/2;
vector<int> F(V+1,0); //0.intit 空间长度V+1
for(int i=0;i<array.size();i++) //1.遍历每一件物品
zeroOnePack(F,array[i],array[i]);
return sum - 2*F.back();
}
.
.
1049.给定vector,string只包含0或者1. 选取最大数量的string,使得0,1总数不超过指定数值
转化:物品ith的二维费用问题 (并不是限定使用次数的多重背包问题)
/*
给定vector<string>,string只包含0或者1. 选取最大数量的string,使得0,1总数不超过指定数值
物品: 字符串s1
费用1: s1中'0'的个数
费用2: s1中'1'的个数
容量1: '0'的个数限制V
容量2: '1'的个数限制U
价值: 1 题目要求: 最大化物品的数量
遍历物品个数,容量(逆序)
物品ith有两种费用,不是多重背包问题。多重背包:物品的使用次数不超过Mi次
*/
#include "func.h"
int V = 0;
int U = 0;
void zeroOnePack(vector<vector<int>>& F, int cost1,int cost2,int values){
for(int i=V;i>=cost1;i--){
for(int j=U;j>=cost2;j--)
F[i][j] = std::max(F[i][j],
F[i-cost1][j-cost2] + values); //二维费用更新
}
}
vector<int> get_0_1_nums(string str){
vector<int> ans(2,0);
for(auto& i : str){
if( i == '0') ans[0] += 1;
else ans[1] += 1;
}
return ans;
}
int findMaxForm(vector<string>& strs,int m,int n){
V = m;
U = n;
vector<vector<int>>F(V+1,vector<int>(U+1,0)); //init; 注意二维费用初始化***
for(auto& str : strs) {
vector<int> nums_0_1 = get_0_1_nums(str);
zeroOnePack(F, nums_0_1[0], nums_0_1[1], 1);
}
return F[V][U];
}