We have a two dimensional matrix A where each value is 0 or 1.
A move consists of choosing any row or column, and toggling each value in that row or column: changing all 0s to 1s, and all 1s to 0s. (可以选择一行或者一列,将所有0换成1,将所有1换成0)
After making any number of moves, every row of this matrix is interpreted as a binary number, and the score of the matrix is the sum of these numbers.(最后每行数字被看作二进制数,进算出所有行二进制数的和,作为score)
Returnthe highest possible score.
Example 1:
Input: [ [0, 0, 1, 1],
[1, 0, 1, 0],
[1, 1, 0, 0] ]
Output: 39
Explanation:
Toggled to [ [1, 1, 1, 1],
[1, 0, 0, 1],
[1, 1, 1, 1] ]
0b1111 + 0b1001 + 0b1111 =15 + 9 + 15 = 39
思路:
最直观的想法就是,二进制越往左越决定整个数的大小,比如1000大于0111,所以需要先通过flip将所有行的第一位变成1(后边的都没有第一位重要),后边从第二列开始往后,让每一列中的1尽可能多(每一列的1重要程度一样)。由于除了0就是1,所以知道每一列中有多少1,就知道有多少0,max就知道这一列通过flip最多有多少个1(不需要真的进行flip操作),这样算到最后一列就知道最大sum是多少了。
int matrixScore(vector<vector<int>>& A)
{
// m 行 n 列
int m = A.size();
int n = A[0].size();
int sum = 0;
for (int i = 0; i < m; i++)
{
if(A[i][0] == 0)
{
for (int t = 0; t < n; t++)
{
if(A[i][t] == 0)
A[i][t] = 1;
else
A[i][t] = 0;
}
}
}
sum = (1 << (n - 1)) * m;
for(int i = 1; i < n; i++) // 从第二列开始
{
int cnt = 0;
for (int j = 0; j < m; j++)
cnt += A[j][i]; // 记录这一列有多少1
sum += max(cnt, m - cnt) * (1 << n - 1 - i);
}
return sum;
}
想到后边的不需要真正进行flip操作,就想到其实一次flip操作都不需要,在每列计算时每次只需要判断,只需要判断这个数和跟他同一行的第一位数是不是一样,就知道假象的翻转后这个数是多少了,因为每一行要不flip,要不就flip一次,只要一样,这个数一定要从0变成1,或者保持是1不变(也就是这个数跟这一行第一位数一样,那假想的flip之后它一定是1),这样就省略了flip每一行让第一位数变为1的过程。
int matrixScore(vector<vector<int>> A)
{
int M = A.size(), N = A[0].size();
int res = (1 << (N - 1)) * M;
for (int j = 1; j < N; j++) // 计算每一行的值,求和
{
int cur = 0;
for (int i = 0; i < M; i++)
cur += A[i][j] == A[i][0];
res += max(cur, M - cur) * (1 << (N - j - 1));
}
return res;
}