题目:
吃完年夜饭,亲戚们总是要坐下打打牌,打打麻将。
而徐老师不会打牌也不会打麻将,没有办法加入群聊,只能一个人默默的躲在角落画圈圈
聪明的徐老师想要给自己找点游戏玩打发时间,她在手机上找到了一种纸牌游戏
这个纸牌游戏一开始有一个 n * mn∗m 的矩阵,矩阵的每个单元上都放着一张带有点数的纸牌,有的纸牌正面朝上,有的纸牌背面朝上
游戏把正面朝上的牌看做正数,把背面朝上的牌看做负数,那么就得到了一个有正有负的数字矩阵
而游戏规则是这样的,每次可以选择两张相邻的纸牌,并同时翻转它们,游戏里一张牌只和它上下左右四张牌相邻
例如有两张牌的是 1,-21,−2 ,同时翻转它们会变成 -1,2−1,2
而游戏的最终得分是将所有点数相加的和,现在徐老师想知道如果操作次数无限,最多可以获得多少分
输入格式
输入第一行包含一个正整数 TT 表示共有 TT 组测试数据
对于每组测试数据:
输入第一行包含两个整数 n,mn,m,表示矩阵大小
接下来 nn 行,每行包含 mm 个整数 a_{i,j}ai,j 分别表示第 ii 行第 jj 列的这张牌,正数表示正面朝上,负数表示背面朝上
对于 40\%40% 的数据,T \leq 10, 1 \leq n,m,a_i \leq 10T≤10,1≤n,m,ai≤10
对于 100\%100% 的数据,T \leq 10, 1 \leq n,m \leq 500, -100 \leq a_i \leq 100T≤10,1≤n,m≤500,−100≤ai≤100
输出格式
对于每组测试数据输出一个整数,表示最多能获得的分数
样例
输入数据 1
2
2 2
-2 2
-2 2
3 3
-2 -2 -2
-2 0 -2
-2 -2 -2
输出数据 1
8
16
这道题考的是思维。
思路:从题目可以看出
如果2个数分别为a和b
1.a为负数,b为负数,那么操作之后a,b就都变成正数了
2.a为负数,b为正数,那么操作之后a变成正数,b就变成负数了
3.a为正数,b为负数,那么操作之后a变成负数,b就变成正数了
4.a为正数,b为正数,那么操作之后a,b就都变成负数了
通过题意可知,如果出现第4种情况那么是不需要操作的,因为如果操作了就不能使最后的总和最大
那么题目在2,3种情况中可以看成负号在转移位置
那么有两种情况
{
1.负数有偶数个:那么就可以根据2,3的操作把负数弄到一块,在用1的操作抵消负号
2.负数有奇数给:那么先用上面的操作,再剩余一个负号(注意,这个负号必须要是矩阵中的最小值,这样才能使总和最大!)
}
综上所述,代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
ll k,m,n,r,t,x,y,ans,cnt,len,res,sum,tmp,a[510][510];
int main()
{
cin>>t;
while(t--)
{
cnt = 0;
sum = 0;
tmp = inf;
cin>>n>>m;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin>>a[i][j];
if(a[i][j] < 0)
{
cnt++;
}
sum += abs(a[i][j]);
tmp = min(tmp,abs(a[i][j]));
}
}
if(cnt % 2 != 0) sum -= 2 * tmp;
cout<<sum<<endl;
}
return 0;
}