力扣 6173. 被列覆盖的最多行数
题目大意
给出一个 n 行 m 列的二维二进制矩阵(只有 0 和 1 两个数),再给出一个数 cols 表示你一共要选出 cols 列。对于每一行,如果这一行中的所有 1 都在你选中的列中,那么称此行被覆盖。
问:最多能有多少行被覆盖?
题意解析
知识点:二进制枚举
题目数据很小,矩阵最多 12 X 12 ,因此我们可以使用二进制枚举来完成此题。
对于某一个矩阵列数为 m ,如果我们可以选择任意列数,那么通过高中学习的排列组合知识,我们可以得到 Cm0 一直加到 Cmm 种选择,也就是 2m 种选择,也正好对应了 0 到 2m 的二进制表示(0 表示不选择,1 表示选择)。
我们再通过处理过滤掉二进制表示中 1 的个数不等于 cols 的情况,然后再带入矩阵中,找到哪一种选择的覆盖层数最大即可。
代码
class Solution {
public:
int lowbit(int x)
{//计算某个数的二进制表示中 1 的个数
int ans=0;
while(x)
{
ans++;
x-=x&-x;
}
return ans;
}
int maximumRows(vector<vector<int>>& mat, int cols)
{
int n=mat.size(),m=mat[0].size(); //n行,m列
// cout<<n<<' '<<m<<endl;
int ans=0;
for(int i=0;i<1<<m;i++)
{//枚举所有选择
int res=0;
if(lowbit(i)!=cols) continue;//过滤掉不符合情况的选择
for(int j=0;j<n;j++)
{//对于某一种情况,遍历矩阵判断覆盖层数
bool flag=true;
for(int k=0;k<m;k++)
{
//对于某一层,如果有一列是 1,但是我们这一列没有选择,那么我们这一层就没有被覆盖
if(mat[j][k]&&(i>>k&1)==0) flag=false;
// cout<<mat[j][k]<<' '<<(i>>k&1)<<' '<<flag<<endl;
}
res+=flag;
// cout<<endl;
}
// cout<<res<<' ';
ans=max(ans,res);
}
return ans;
}
};