XTU-OJ 1412-Rotate Again

大家可能也发现我是实时更新的,所以大家可以点赞、评论,如果讲解的不够详细或者看不懂的都可以留言。多给我些反馈,可以让我更好的编写博客内容。(但是别催更啊~~)

题目描述

一个4×4的矩阵,我们可以把矩阵看成内外两圈,我们可以把外圈按顺时钟或者逆时钟转动,每次转动一个格子。 我们想得到一个2×2的子矩阵,使得这个子矩阵4个元素的累加和最大。请问最大子矩阵的元素累加和是多少?

输入

第一行是一个整数T(1≤T≤1000),表示样例的个数。 每个样例占4行,每行4个整数,所有元素在[1,1000]范围内。

输出

每行输出一个样例的结果。

样例输入

2
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
1 1 2 2
3 3 4 4
2 2 1 1
4 4 3 3

样例输出

56
15

提示

第一个样例,逆时钟旋转1格,得到最大子矩阵为

11 16
14 15


第二个样例,逆时钟旋转5格,得到最大子矩阵为

3 4
4 4

解题思路:本题最大的 2 * 2矩阵 就三种情况。 1: 内圈四元素、2: 内圈1元素+外圈3元素、 3: 内圈2元素+外圈2元素。  这题的两种方法,一种就是纯粹的用二维数组,然后一次一次的转动外圈,暴力求解 ,另一种就是把二维数组数据转化为一维数组,把外圈和内圈的数分别存在一个一维数组中,过程可能有些绕,但是解题思路还是很明确的。       

这里我用的是第二种方法:代码写的有些绕,就不写详细的题解了,直接对着代码讲解。

maxiner  == 内圈四个元素之和,in1 == 内圈四个元素中最大值,in2 == 内圈四个元素中两最大相邻数之和,out2 == 外圈十二个元素中两最大相邻数之和, out3 == 外圈十二个元素中三最大相邻数之和。

scanF() 输入函数之后,就把 外圈内圈元素都存在了一维数组中, 在comput()中 有个 取模的运算,这使一维数组转化成一个圈,实现了轮转的功能(到数组末尾后又跳转到数组开头)。

43行交换函数,把inter[2] 和 inter[3] 交换位置,是因为我用for循环直接输入,存入内圈数组的 第二个数就和第三个数相邻了。但实际上不是,第二是和第四相邻,第一和第三相邻的。(能否理解)

其他的应该看代码上的注释可以看懂,如有疑惑的请留言。

AC代码:

#include <stdio.h>

int outer[15],inter[5];
int left,right,ins,ans;
int T,maxiner,in1,in2,out2,out3;

void Swap(int &x,int &y){           // 交换函数,就为了换一次,小题大做了,但还是手痒
    int t;
    t = x, x = y, y = t;
}

int Max(int x,int y,int z)          // 比较函数,返回(x,y,z)中的最大值
{
    if (x >= y && x >= z)  return x;
    if (y >= x && y >= z)  return y;
    if (z >= x && z >= y)  return z;
    return 0;
}

void scanF()
{
    left = 6,right = 5,ins = -1;
    maxiner = in1 = in2 = out2 = out3 = 0;
    for (int i = 1; i <= 4; i ++)               // 输入第一行
        scanf("%d",&outer[++right]);
    for (int i = 1; i <= 2; i ++)               // 输入第二三行
    {
        scanf("%d",&outer[--left]);
        for (int j = 1; j <= 2; j ++)           // 注意这里直接输入有误,还需处理(43行)
        {
            scanf("%d",&inter[++ins]);
            maxiner += inter[ins];              //  内圈 2*2 元素和
            if (inter[ins] > in1)   in1 = inter[ins];   // 内圈最大值
        }
        scanf("%d",&outer[++right]);   
    }
    for (int i = 1; i <= 4; i ++)               // 输入第四行
        scanf("%d",&outer[--left]);
}

void comput()
{
    Swap(inter[2],inter[3]);
    for (int i = 0; i < 4; i ++)
    {
        int t1 = inter[i]+inter[(i+1)%4];
        if (t1 > in2)    in2 = t1;               // 内圈最大的两个相邻元素和
    }
    for (int i = 0; i < 12; i ++)
    {
        int t2 = outer[i] + outer[(i+1)%12];
        int t3 = t2 + outer[(i+2)%12];
        if (t2 > out2)      out2 = t2;          // 外圈最大的两个相邻元素和
        if (t3 > out3)      out3 = t3;          // 外圈最大的三个相邻元素和
    }
}

int main()
{
    scanf("%d",&T);
    while ( T --)
    {
        scanF();
        comput();
        ans = Max(maxiner,in1+out3,in2+out2);
        printf("%d\n",ans);
    }
    return 0;
}

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值