题目链接:https://codeforces.com/problemset/problem/173/C
题目大意:
对一个边长k为奇数的正方形,有一条螺旋线(黑色)。

现在给你一个长宽分别为n, m的矩阵。问你子正方形的螺旋线和的最大值。

思路:我们枚举每一个子正方形。有O(n^3)个,如果我们能够在O(1)求出每一个子正方形的螺旋线和,就可以了。

我们观察对一个正方形。

内部是一个小的子正方形。而白色部分就是子正方形的螺旋线的和。

那么我们用f[i][j][k]:在(i, j)边长为k的正方形螺旋线的和。如果我们最先枚举k就可以进行滚动数组优化。

#include <bits/stdc++.h>
#define LL long long
using namespace std;

int a[505][505];
int sum[505][505];
int f[505][505][2];

int S(int x, int y, int i, int j){
    return sum[i][j]-sum[i][y-1]-sum[x-1][j]+sum[x-1][y-1];
}

int main(){

    int n, m;
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            scanf("%d", &a[i][j]);
            f[i][j][0]=a[i][j];
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
        }
    }

    int ans=-1<<30;
    for(int len=3; len<=min(n, m); len+=2){
        for(int i=1; i<=n; i++){
            if(i+len-1>n) continue;
            for(int j=1; j<=m; j++){
                if(j+len-1>m) continue;
                f[i][j][1]=S(i, j, i+len-1, j+len-1);
                f[i][j][1]-=f[i+1][j+1][0];
                f[i][j][1]-=a[i+1][j];
                ans=max(ans, f[i][j][1]);
            }
        }

        for(int i=1; i<=n; i++){
            for(int j=1; j<=m; j++){
                f[i][j][0]=f[i][j][1];
            }
        }
    }

    printf("%d\n", ans);

    return 0;
}