技巧:
贪心(两个维度 改变会影响前后),需要用枚举办法固定一个维度 然后贪心的选择另外一个维度。
思路:
用01串模拟要不要当前行(枚举)
在行固定的情况下贪心选最优的列 并更新结果
实现:
package main
import (
"fmt"
)
var ans int
func main() {
// Input
var n, m, k int
fmt.Scan(&n, &m, &k)
arr := make([][]int, n)
for i := 0; i < n; i++ {
arr[i] = make([]int, m)
for j := 0; j < m; j++ {
fmt.Scan(&arr[i][j])
}
}
process(arr, n, m, k)
fmt.Println(ans)
}
// 枚举(n) + 贪心(m)
func process(arr [][]int, n, m, k int) {
tmp := 1 << n
for i := 0; i < tmp; i++ {
cnt := get1Cnt(i)
if k < cnt {
continue
}
sum := 0
// 1 计算行的总和
for row := 0; row < n; row++ {
if (i>>row)&1 == 1 { // 该位若是1 代表选了这行
for j := 0; j < m; j++ {
sum += arr[row][j]
}
}
}
// 2 计算列的总和 取得前 colK 大的前缀和
colK := k - cnt // 剩余给列操作的次数
colSumArr := make([]int, colK)
for col := 0; colK > 0 && col < m; col++ {
currColSum := 0
for row := 0; row < n; row++ {
if (i>>row)&1 == 0 {
currColSum += arr[row][col]
}
}
// 利用插入排序思想只保存前K组和最大的列
if currColSum > colSumArr[colK - 1] {
colSumArr[colK-1] = currColSum
}
for j := colK - 1; j > 0 && colSumArr[j] > colSumArr[j-1]; j-- {
colSumArr[j], colSumArr[j-1] = colSumArr[j-1], colSumArr[j]
}
}
for _, v := range colSumArr {
sum += v
}
// 3 更新结果
if sum > ans {
ans = sum
}
}
}
// 获取1的数量
func get1Cnt(x int) int {
cnt := 0
for x != 0 {
if x&1 == 1 {
cnt++
}
x >>= 1
}
return cnt
}

京公网安备 11010502036488号