[CF1447B]Numbers Box

[CF1447B]Numbers Box

题目传送门

一道思路十分好想的 水题 贪心题。

题目大意:

\(t\) 次提问,每次提问输入两个数 \(m,n\) 表示行和列,输入 \(a_{ij}\) 表示第 \(i\)\(j\) 列中的数,每次可将两个相邻的数乘 \({-1}\) 使最终矩阵中所有数相加的和最大

思路:

要使矩阵中所有数之和最大,正数一定要越多越好 ,我们可以将相邻的两个负数都变成正数。

不需要相邻的数才可以变,我们可以选矩阵中任意两个数进行改变,这样一来,我们可以将矩阵中的负数变成 \(n%2\) 个,如果还剩一个负数,还可以将负数随意替换到每一个位置,当然,我们要将它替换到绝对值最小的数上。

实现:

  • \(ans\) 存储每一个输进来的 \(a_{ij}\) 的绝对值:

ans+=abs(a);

  • \(gs\) 记录矩阵中负数的个数:

if(a<0) gs++;

  • \(mn\) 存储 \(a_{ij}\) 的最小绝对值:

mn=min(mn,abs(a));

  • 如果 \(gs\) 为偶数,直接输出 \(ans\) (全部都变正数):

if(gs%2==0) cout<<ans<<endl;

  • 否则输出 \(ans-mn \times 2\) (还剩一个负数):

else cout<<ans-mn*2<<endl;

AC code:

#include<bits/stdc++.h>
using namespace std;
int t,n,m;
int mian()
{
 	cin>>t;
 	while(t--)	//询问t次
 	{
 		int gs=0,ans=0,mn=105;	//初始化
 		cin>>n>>m;
 		for(int i=1,a;i<=n;i++)	//循环整个矩阵
 			for(int j=1;j<=m;j++)
 			{
 				cin>>a;
 				ans+=abs(a);	//ans加上a的绝对值
 				if(a<0)
 					gs++;	//记录负数个数
 				mn=min(mn,abs(a));	//记录最小的绝对值
			}
 		if(gs%2==0)	//全部变正数
 			cout<<ans<<endl;
 		else	//还剩一个负数
 			cout<<ans-mn*2<<endl;	//答案中一个数从正变负,减两遍
 	}
  return 0;
 }
posted @ 2024-08-24 16:03  Hyper_zero  阅读(3)  评论(0编辑  收藏  举报