Skip to content

Commit

Permalink
01背包
Browse files Browse the repository at this point in the history
  • Loading branch information
gdis5251 committed Jun 6, 2021
1 parent e91645c commit 791491b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
1 change: 1 addition & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 91 additions & 0 deletions leet_code/474.一和零/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

/***
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
----------------------------------------------------------------------------------------------------------
示例 1:
输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。
----------------------------------------------------------------------------------------------------------
示例 2:
输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。
*/


/***
思路:把总共的 0 和 1 的个数视为背包的容量,每一个字符串视为装进背包的物品。这道题就可以使用 0-1 背包问题的思路完成,这里的目标值是能放进背包的字符串的数量。
动态规划的思路是:物品一个一个尝试,容量一点一点尝试,每个物品分类讨论的标准是:选与不选。
定义状态:尝试题目问啥,就把啥定义成状态。dp[i][j][k] 表示输入字符串在子区间 [0, i] 能够使用 j 个 0 和 k 个 1 的字符串的最大数量。
状态转移方程:
dp[i][j][k]= \begin{cases} dp[i - 1][j][k], & 不选择当前考虑的字符串,至少是这个数值\\ dp[i - 1][j - 当前字符串使用 \;0\; 的个数][k - 当前字符串使用 \;1\; 的个数] + 1 & 选择当前考虑的字符串 \end{cases}
dp[i][j][k]={
dp[i−1][j][k],
dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1
不选择当前考虑的字符串,至少是这个数值
选择当前考虑的字符串
初始化:为了避免分类讨论,通常多设置一行。这里可以认为,第 00 个字符串是空串。第 00 行默认初始化为 00。
输出:输出是最后一个状态,即:dp[len][m][n]。
*/

func findMaxForm(strs []string, m int, n int) int {
dp := make([][][]int, len(strs) + 1)
for i := range dp {
dp[i] = make([][]int, m + 1)
for j := range dp[i] {
dp[i][j] = make([]int, n + 1)
}
}

for i, str := range strs {
zero, one := calZeroAndOne(str)
for j := 0; j <= m; j++ {
for k := 0; k <= n; k++ {
dp[i + 1][j][k] = dp[i][j][k]
if j >= zero && k >= one {
dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j - zero][k - one] + 1)
}
}
}
}

return dp[len(strs)][m][n]
}

func calZeroAndOne(num string) (int, int) {
zero := 0
one := 0
for _, c := range num {
if c == '0' {
zero++
} else {
one++
}
}
return zero, one
}

func max(lhs, rhs int) int {
if lhs > rhs {
return lhs
}
return rhs
}
7 changes: 6 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package main

import "fmt"
import (
"fmt"
"reflect"
)

func main() {
chan1 := make(chan int, 1)
Expand All @@ -21,4 +24,6 @@ func main() {
}
}
}()

reflect.SliceHeader{}
}

0 comments on commit 791491b

Please sign in to comment.