每日一题--多属性的01背包问题
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题--多属性的01背包问题相关的知识,希望对你有一定的参考价值。
题目
题目详解
什么是多属性的背包问题?比如对于这道题,它可以看作是一个具有装下物品两个属性的背包(装下0和1),它的容量可以看作是
[j][k]
可用二维数组
来表示,而外面一层和普通的01背包问题一样,用于表示在有多少个物体的情况下装下物体的个数
。
- 那么dp数组定义如下–
dp[i][j][k]表示给出前i个物体,并且背包容量为[i][k](装下1和0的容量)的情况下所能装下的最多物体
,由于对于每个物体是一个字符串,每个字符串有0或者1两种属性,可设计一个函数用于专门求0和1 的个数 - 对于此题dp关系为:
dp[i][j][k] = dp[i-1][j][k](no pack)+dp[i-1][j-count(0)][k-count(1)](pack)
. - 最后由于是背包问题base case肯定是背包容量为0以及给出物品数为0的情况,即
dp[0][..][..] = 0,dp[..][0][0] = 0
,根据三维空间画图可知遍历方向是从左往右从下往上
.
三维空间实现多属性01背包
class Solution {
public:
//三维数组实现dp关系
//用于计数每个字符串的0和1用长度为2的数组返回
vector<int> getZerosOnes(string& str) {
vector<int> zerosOnes(2);
int length = str.length();
for (int i = 0; i < length; i++) {
zerosOnes[str[i] - '0']++;
}
return zerosOnes;
}
int findMaxForm(vector<string>& strs, int m, int n) {
int length = strs.size();
//三维vector数组
vector<vector<vector<int>>> dp(length + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));//最外面一层是表示放入前i个物品后,背包容量为j和k的最多容量(最多放几个物品,通过每个物品的放与不放来枚举得到)本质上是一个三维的01背包问题
for (int i = 1; i <= length; i++) {
//右值引用得到函数返回值,减少空间消耗
vector<int>&& zerosOnes = getZerosOnes(strs[i - 1]);
int zeros = zerosOnes[0], ones = zerosOnes[1];
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
dp[i][j][k] = dp[i - 1][j][k];
if (j >= zeros && k >= ones) {
dp[i][j][k] = max(dp[i-1][j][k], dp[i - 1][j - zeros][k - ones] + 1);
}
}
}
}
return dp[length][m][n];
}
};
滚动数组到二维空间
由于每个结果只和上一行的结果有关,故可直接优化。
由于要保证每个为上一行的结果
,此时需要背包逆向遍历。
class Solution {
public:
vector<int> getZerosOnes(string& str) {
vector<int> zerosOnes(2);
int length = str.length();
for (int i = 0; i < length; i++) {
zerosOnes[str[i] - '0']++;
}
return zerosOnes;
}
int findMaxForm(vector<string>& strs, int m, int n) {
int length = strs.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 0; i < length; i++) {
vector<int>&& zerosOnes = getZerosOnes(strs[i]);
int zeros = zerosOnes[0], ones = zerosOnes[1];
//背包容量逆向遍历
for (int j = m; j >= zeros; j--) {
for (int k = n; k >= ones; k--) {
dp[j][k] = max(dp[j][k], dp[j - zeros][k - ones] + 1);
}
}
}
return dp[m][n];
}
};
以上是关于每日一题--多属性的01背包问题的主要内容,如果未能解决你的问题,请参考以下文章