codeforces 173C Spiral Maximum(简单预处理)

本文概述了AI音视频处理领域的关键技术,包括视频分割、语义识别、自动驾驶、AR、SLAM、物体检测与识别、语音识别变声等,为开发者提供了一个全面的技术视角。
C. Spiral Maximum
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Let's consider a k × k square, divided into unit squares. Please note that k ≥ 3 and is odd. We'll paint squares starting from the upper left square in the following order: first we move to the right, then down, then to the left, then up, then to the right again and so on. We finish moving in some direction in one of two cases: either we've reached the square's border or the square following after the next square is already painted. We finish painting at the moment when we cannot move in any direction and paint a square. The figure that consists of the painted squares is a spiral.

The figure shows examples of spirals for k = 3, 5, 7, 9.

You have an n × m table, each of its cells contains a number. Let's consider all possible spirals, formed by the table cells. It means that we consider all spirals of any size that don't go beyond the borders of the table. Let's find the sum of the numbers of the cells that form the spiral. You have to find the maximum of those values among all spirals.

Input

The first line contains two integers n and m (3 ≤ n, m ≤ 500) — the sizes of the table.

Each of the next n lines contains m space-separated integers: the j-th number in the i-th line aij ( - 1000 ≤ aij ≤ 1000) is the number recorded in the j-th cell of the i-th row of the table.

Output

Print a single number — the maximum sum of numbers among all spirals.

Sample test(s)
input
6 5
0 0 0 0 0
1 1 1 1 1
0 0 0 0 1
1 1 1 0 1
1 0 0 0 1
1 1 1 1 1
output
17
input
3 3
1 1 1
1 0 0
1 1 1
output
6
input
6 6
-3 2 0 1 5 -1
4 -1 2 -3 0 1
-5 1 2 4 1 -2
0 -2 1 3 -1 2
3 1 4 -3 -2 0
-1 2 -1 3 1 2
output
13
Note

In the first sample the spiral with maximum sum will cover all 1's of the table.

In the second sample the spiral may cover only six 1's.

题意:

给你一个n * m (3 ≤ n, m ≤ 500)的矩阵。定义了一种螺旋矩阵。矩阵的边长为>=3的奇数。矩阵的值为矩阵的螺旋线上格子的权值和。螺旋线的定义为。从矩阵的左上角开始。依次按左,下,右,上的方向前进。转向的条件是当前格子的当前方向的下下个格子被走过了或到了矩阵的边界。结束的条件是不能再前进了。现在告诉你权值矩阵。要你找出子矩阵的最大权值。

思路:

为了减少频繁的求和操作我们预处理出rsum[i][j],第i行的前j项和。csum[j][i]。第j列的前i项和。通过观察会发现n=7比n=3.多出的部分和n=9比n=5多出的部分都是外围的不到一圈加一点。所以n=3,7,11,15的可以一圈一圈的加。n=5,9,13的和也可以一圈一圈的加。所以我们只需要枚举子矩阵的左上角和长度就可以算出最大权值了。最大时间复杂度为(500*500*250).这是最坏的估计。实际比这好的多。

详细见代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int maxn=100010;
int rsum[510][510],csum[510][510],val[510][510];

int main()
{
    int n,m,i,j,ans,sum,x1,y1,x2,y2;

    while(~scanf("%d%d",&n,&m))
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                scanf("%d",&val[i][j]);
        for(i=1;i<=n;i++)
        {
            rsum[i][0]=0;
            for(j=1;j<=m;j++)
                rsum[i][j]=rsum[i][j-1]+val[i][j];
        }
        for(j=1;j<=m;j++)
        {
            csum[j][0]=0;
            for(i=1;i<=n;i++)
                csum[j][i]=csum[j][i-1]+val[i][j];
        }
        ans=-INF;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                x1=i,y1=j;
                x2=x1+2,y2=y1+2;
                if(x2<=n&&y2<=m)//3,7,11,15....
                {
                    sum=rsum[x1][y2]-rsum[x1][y1-1]+csum[y2][x2]-csum[y2][x1]+rsum[x2][y2-1]-rsum[x2][y1-1];
                    ans=max(ans,sum);
                    while(x1-2>=1&&y1-2>=1&&x2+2<=n&&y2+2<=m)
                    {
                        x1-=2,y1-=2,x2+=2,y2+=2;
                        sum+=rsum[x1][y2]-rsum[x1][y1-1]+csum[y2][x2]-csum[y2][x1]+rsum[x2][y2-1]-rsum[x2][y1];
                        sum+=csum[y1][x2]-csum[y1][x1+1]+val[x1+2][y1+1];
                        ans=max(ans,sum);
                    }
                }
                x1=i,y1=j;
                x2=x1+4,y2=y1+4;
                if(x2<=n&&y2<=m)//5,9,13,17.....
                {
                    sum=rsum[x1][y2]-rsum[x1][y1-1]+csum[y2][x2]-csum[y2][x1]+rsum[x2][y2-1]-rsum[x2][y1];
                    sum+=csum[y1][x2]-csum[y1][x1+1]+val[x1+2][y1+1]+val[x1+2][y1+2];
                    ans=max(ans,sum);
                    while(x1-2>=1&&y1-2>=1&&x2+2<=n&&y2+2<=m)
                    {
                        x1-=2,y1-=2,x2+=2,y2+=2;
                        sum+=rsum[x1][y2]-rsum[x1][y1-1]+csum[y2][x2]-csum[y2][x1]+rsum[x2][y2-1]-rsum[x2][y1];
                        sum+=csum[y1][x2]-csum[y1][x1+1]+val[x1+2][y1+1];
                        ans=max(ans,sum);
                    }
                }
            }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值