问题描述
有一个二维矩阵 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
输入说明
首先输入矩阵的行数m、列数n,
然后输入m行,每行n个数字,每个数字都是0或1。
1 <= m <= 20
1 <= n <= 20
输出说明
输出一个整数
输入范例
3 4
0 0 1 1
1 0 1 0
1 1 0 0
输出范例
39
实现思路
为了使最终结果最大,则矩阵每一行的最左边都必须为1,然后让每列的1尽可能的多。
1、让每行第一个元素不为1的行反转。
2、行处理完之后,遍历除了第一列的所有列,判断此时每列1的个数,若1的个数小于0的个数则进行反转。
实现代码
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int fun(vector<vector<int>> &num){
int res = 0;
if(num.size() == 0) return res;
int m = num.size();
int n = num[0].size();
//行变后
res = m * pow(2,n - 1);//第一列都变1
//处理除了第一列以外的列
for(int i = 1;i<n;i++){
int tem = 0;//记录1的个数
for(int j = 0;j<m;j++){
if(num[j][0] == 1){//该行的第一个元素本来就为1,所以该行没有反转,此时对应列的值就是原本的值
tem += num[j][i];
}else{//该行第一个元素原本为0,进行反转后,对应列的值会变化,0变1,1变0(此时用1-num[j][i]就是反转后的值)
tem += (1 - num[j][i]);
}
}
int k = max(tem,m - tem);
res += k * pow(2,n - i - 1);
}
return res;
}
int main()
{
int m,n,temp;
cin>>m>>n;
vector<vector<int>> num;
vector<int> temps;
for(int i = 0;i<m;i++){
temps.clear();
for(int j = 0;j<n;j++){
cin>>temp;
temps.push_back(temp);
}
num.push_back(temps);
}
int res = fun(num);
cout<<res;
return 0;
}