欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

861. 翻转矩阵后的得分

程序员文章站 2022-07-12 12:31:47
...

有一个二维矩阵 A 其中每个元素的值为 0 或 1 。

移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0

在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。

返回尽可能高的分数。

 

示例:

输入:[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出:39
解释:
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39

 

提示:

  1. 1 <= A.length <= 20
  2. 1 <= A[0].length <= 20
  3. A[i][j] 是 0 或 1

思路:这题乍一看上去没有思路,开始想着遍历是不可能遍历的

我们先观察一行有什么特征,如果一行的第一个元素是零,我们毫无疑问的把它反转,因为二进制的特点就是相同位置上有1的比没1的一定要大

再我们看一下列,如果一个列中0,1的数量分别为m,n;

那么有三种情况:

1.m>n  说明零的数量比较多,如果反转一下,1的数量就比较多了,较之之前来说,就是赚的

2.m=n 反转不反转都一样

3.m<n 说明已经达到了比较理想的情况

于是我们先按行遍历每一行的第一个元素,如果是零就反转

第二步遍历每一列,计算每一列中0的数量,如果大于等于一半,那么就反转

CODE:

class Solution {
public:
    void transrow(vector<int>&A)
    {
        for (int i=0;i<A.size();++i)
            A[i]^=1;
    }
    int calculate(vector<int>A)
    {
        int cnt=0;
        int n=A.size();
        for(int i=0;i<n;i++)
        {
            if(A[i])cnt|=1<<(n-1-i);
        }
        return cnt;
    }
    int matrixScore(vector<vector<int>>& A) {
        int row=A.size();
        int col=A[0].size();
        int a = row%2==0?row/2:(row+1)/2;
        cout<<a<<endl;
        for(int i=0;i<row;i++)
            if(A[i][0]==0)transrow(A[i]);
        for(int j=0;j<col;++j)
        {   int cnt=0;
            for(int i=0;i<row;i++)
                if(A[i][j]==0)cnt++;
            if(cnt>=a)
            {
                 for(int i=0;i<row;i++)
                    A[i][j]^=1;
            }      
        }
        int res=0;
        for(int i=0;i<row;i++)
        {       
            // cout<<res<<endl;
            res+=calculate(A[i]);
        }
        return res;
    }
};