3763 数字矩阵(思维题)

1. 问题描述:

给定一个 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
来源:https://www.acwing.com/problem/content/description/3766/

2. 思路分析:

这道题目类似于3762题,我们也是需要挖掘一下题目的一些性质,可以发现对于矩阵中任意两个位置的数字我们都可以通过一条路径使得路径端点处的数字变为相反数,路径中的其余点是不变的(只有端点处乘了一次-1所以变为相反数),所以要想使得最终矩阵中的和最大我们需要尽可能使得负数变为正数,所以每一次我们可以选择两个负数将其变为正数,当负数的个数为偶数个的时候我们可以通过两两配对这样最终所有的负数都会变为正数,当负数的个数为奇数个的时候那么最终一定会剩下一个负数这个时候最终留下来的负数应该是绝对值最小的那个负数这样总和才可以最大,当我们发现这个性质之后问题就变得比较好处理了。

3. 代码如下:

class Solution:
    def process(self):
        T = int(input())
        for i in range(T):
            n, m = map(int, input().split())
            g = list()
            for j in range(n):
                g.append(list(map(int, input().split())))
            # count计算负数的个数
            res = count = 0
            # minw求解绝对值最小的值
            minw = 10 ** 8
            for j in range(n):
                for k in range(m):
                    res += abs(g[j][k])
                    if g[j][k] < 0:
                        count += 1
                    minw = min(minw, abs(g[j][k]))
            if count % 2:
                # 应该减去两倍的minw
                print(res - 2 * minw)
            else:
                print(res)


if __name__ == '__main__':
    Solution().process()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值