0%

2397. 被列覆盖的最多行数

2397.被列覆盖的最多行数

题目描述:

给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix ;另给你一个整数 numSelect,表示你必须从 matrix 中选择的 不同 列的数量。

如果一行中所有的 1 都被你选中的列所覆盖,则认为这一行被 覆盖 了。

形式上,假设 s = {c1, c2, ...., cnumSelect} 是你选择的列的集合。对于矩阵中的某一行 row ,如果满足下述条件,则认为这一行被集合 s 覆盖

  • 对于满足 matrix[row][col] == 1 的每个单元格 matrix[row][col]0 <= col <= n - 1),col 均存在于 s 中,或者
  • row不存在 值为 1 的单元格。

你需要从矩阵中选出 numSelect 个列,使集合覆盖的行数最大化。

返回一个整数,表示可以由 numSelect 列构成的集合 覆盖最大行数

数据范围:

$1\le m, n \le 12, 1\le numSelect \le n$

题解:

数据范围很小,应该是暴力枚举。

子集型枚举,可以二进制枚举,或者枚举选与不选,或者枚举选哪一列。

二进制枚举,然后使用 __builtin_popcount 统计整数内有多少个 1,等于 $numSelect$ 的可以算一下覆盖行数。

选与不选,记录一下选了多少列了,如果剩余的不够,直接返回剪枝。

选哪一列,每次只能选 $step$ 后面的列,避免重复,同样也记录选了多少列了,如果剩余的不够,直接返回剪枝。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int ans = 0;
vector<bool> vis;
vector<int> status;
int n, m;
void dfs(int step, int selectCnt, int selectStatus, int numSelect)
{
if (selectCnt == numSelect)
{
int tmp = 0;
for (auto &s : status)
{
if ((s | selectStatus) == selectStatus)
{
tmp++;
}
}
ans = max(ans, tmp);
return;
}
if (step >= m)
return;
if (selectCnt + (m - step) < numSelect)
return;
// 选与不选
// 选
selectStatus |= (1 << step);
dfs(step + 1, selectCnt + 1, selectStatus, numSelect);
selectStatus &= ~(1 << step);
dfs(step + 1, selectCnt, selectStatus, numSelect);
}
int maximumRows(vector<vector<int>> &matrix, int numSelect)
{
n = matrix.size(), m = matrix[0].size();
status.resize(n);
vis.resize(n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (matrix[i][j])
{
status[i] |= (1 << j);
}
}
}
dfs(0, 0, 0, numSelect);
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int ans = 0;
vector<bool> vis;
vector<int> status;
int n, m;
int maximumRows(vector<vector<int>> &matrix, int numSelect)
{
n = matrix.size(), m = matrix[0].size();
status.resize(n);
vis.resize(n);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (matrix[i][j])
{
status[i] |= (1 << j);
}
}
}
for (int i = 0; i < (1 << m); ++i)
{
if (__builtin_popcount(i) != numSelect)
continue;
int tmp = 0;
for (auto &s : status)
{
if ((s | i) == i)
tmp++;
}
ans = max(ans, tmp);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int ans = 0;
vector<int> status;
int n, m;
void dfs(int step, int selectCnt, int selectStatus, int numSelect)
{
if (selectCnt == numSelect)
{
int tmp = 0;
for (auto &s : status)
{
if ((s | selectStatus) == selectStatus)
{
tmp++;
}
}
ans = max(ans, tmp);
return;
}
if (selectCnt + (m - step) < numSelect)
return;
for (int i = step; i < m; ++i)
{
dfs(i + 1, selectCnt + 1, selectStatus | (1 << i), numSelect);
}
}
int maximumRows(vector<vector<int>> &matrix, int numSelect)
{
n = matrix.size(), m = matrix[0].size();
status.resize(n, 0);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (matrix[i][j])
{
status[i] |= (1 << j);
}
}
}
dfs(0, 0, 0, numSelect);
return ans;
}
};