格式化的代碼求解揹包問題
先驗: 《揹包九講》的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];
}