AcWing 3763. 数字矩阵
题目:
给定一个 n×m 的整数矩阵,其中第 i 行第 j 列的元素为 aij。
你可以进行任意多次如下操作:
选择矩阵中的两个相邻元素,将它们均乘以 −1。
同一个元素可以被选中多次。
你需要通过上述操作,使得矩阵中所有元素的和尽可能大。
计算并输出这个和的最大可能值。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含两个整数 n,m。
接下来 n 行,每行包含 m 个整数,表示整个矩阵,其中第 i 行第 j 列的数为 aij。
输出格式
每组数据输出一行结果,表示矩阵的所有元素的最大可能和。
数据范围
1≤T≤100,
2≤n,m≤10,
−100≤aij≤100
输入样例:
2
2 2
-1 1
1 1
3 4
0 -1 -2 -3
-1 -2 -3 -4
-2 -3 -4 -5
输出样例:
2
30
思路:
本题思路:相邻两个位置可以同时乘上-1,则可以进行延伸到整个矩阵的范围,
一条路线中只有头尾位置的符号改变(变换一次),路线中的其他位置的符号不变(变换两次)
题目说可以进行任意次操作,故可以同时改变矩阵中任意两个元素的符号
题目要求经过操作后求矩阵的最大值,则可以先统计矩阵中的负数的总个数,累加矩阵中所有元素的绝对值
分为两种情况:
1.当矩阵中的负数个数为偶数时,由于可以用时改变任意两个元素的正负,所有直接输出矩阵元素的绝对值之和即可
2.当矩阵中的负数个数为奇数时,仅仅可以修改任意偶数个元素的正负,所有一定会留下一个负数,
最终结果为 所有矩阵元素的绝对值之和 减去 2倍最小绝对值的差
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int main()
{
int n, m, i, j;
int num[15][15] = {0};
int T;
cin>>T;
while (T--)
{
cin>>n>>m;
memset(num,0,sizeof(num));
int count = 0, Min = 1e5, sum = 0;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
{
scanf("%d",&num[i][j]);
sum += abs(num[i][j]);
if (Min > abs(num[i][j]))
Min = abs(num[i][j]);
if (num[i][j] < 0)
count++;
}
if (count % 2)
cout<<sum-2*Min<<endl;
else
cout<<sum<<endl;
}
return 0;
}