Description
给定一个\(n\)行\(m\)列的01矩阵\(matrix\),以及一个整数\(x\)。
你可以选取\(x\)个列,如果这些列能完全覆盖某行全部的1,那就认为是命中该行。
求最多的命中行数。
NOTE: 如果该行是全0,也算命中。
Constraints
- \(1 \le n, m \le 12\)
- \(1 \le x \le m\)
- \(0 \le matrix[i][j] \le 1\)
Solution
答案具有单调性,直接二分答案。
我是傻逼。直接取max就好了枚举个屁的答案。
写都写了,还是贴出来吧,下次做题记得带脑子。
Code
class Solution {
public:
int maximumRows(vector<vector<int>>& matrix, int numSelect) {
int row = matrix.size();
int col = matrix[0].size();
int lo = 0, hi = row;
vector<int> needs(row);
for(auto &need : needs) {
auto &mi = matrix[distance(needs.data(), &need)];
need = accumulate(mi.begin(), mi.end(), 0);
}
auto for_set = [&](int S, auto cond, int target) {
for(int s = 0; s < S; ++s) {
if(cond(s, target)) return true;
}
return false;
};
auto cond = [&](int s, int target) {
auto popcount = [c = 0, t = 0](auto v) mutable {
while(t = v&-v) c++, v-=t;
return c;
};
if(popcount(s) != numSelect) return false;
int cnt[15] {};
for(int i = 0; i < col; ++i) {
if(s >> i & 1 ^ 1) continue;
for(int j = 0; j < row; ++j) {
cnt[j] += matrix[j][i];
}
}
for(auto &need : needs) {
auto idx = distance(needs.data(), &need);
target -= (cnt[idx] == need);
}
return target <= 0;
};
auto check = [&](int target) {
return for_set(1 << col, cond, target);
};
while(lo < hi) {
auto mid = lo + (hi - lo + 1) / 2;
if(check(mid)) lo = mid;
else hi = mid - 1;
}
return lo;
}
};