背包建模:
设计状态:
dp[k][i][j]
:代表考虑前 k
件物品,在数字 1 容量是 i
,数字 0 容量是 j
的条件下的「最大价值」。设计状态转移方程:
dp[k][i][j] = dp[k-1][i][j]
dp[k][i][j] = max( dp[k-1][i][j], dp[k-1][i-当前字符串使用 1 的个数][j-当前字符串使用 0 的个数] + 1 )
事实上,我们还能继续进行空间优化。
再次观察我们的「状态转移方程」发现:f[k][i][j]
不仅仅依赖于上一行,还明确依赖于比 i
小和比 j
小的状态。
即可只依赖于「上一行」中「当前列」的格子,和「前面列」的格子。
因此可直接参考「01 背包的空间优化」方式:
状态表达:
dp[i][j]
:最多有 i
个 0
和 j
个 1
的
s
t
r
s
strs
strs 的最大子集的大小为 dp[i][j]
。状态转移方程:
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
for (string str : strs) { // 遍历当前物品
int oneNum = 0, zeroNum = 0; // 记录当前物品的 1、0 的数量
for (char c : str)
c == '0' ? zeroNum++ : oneNum++;
for (int i = m; i >= zeroNum; i--) // 从后向前遍历背包容量
for (int j = n; j >= oneNum; j--)
dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
}
return dp[m][n];
}
};