CF173C Spiral Maximum 题解

题意

求一个 \(n \times m\) 的矩形中螺旋形最大的数字和。

分析

看图不难发现,以同一个方块为中心的两个边长差为 \(2\) 的螺旋形的数字和其实是有规律的,大一些的螺旋形的数字和就等于整个正方形的数字和减去小一些的螺旋形数字和再减去小螺旋形左上角左侧的数。因此我们先用二维前缀和预处理每一个正方形的面积,然后循环每一个中心,递推出以 \((i,j)\) 为中心,从 \((i,j)\) 向边缘有 \(k\) 个方格的螺旋形的数字和。

dp[i][j][k]=sum(i,j,k)-dp[i][j][k-1]-a[i-k+1][j-k],ans=qmax(ans,dp[i][j][k]); 

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int MAXN=503;
const int inf=2139062143;
inline void qread(){}template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
{
	register T1 x=0;register bool f=false;char ch=getchar();
	while(ch<'0') f|=(ch=='-'),ch=getchar();
	while(ch>='0') x=(x*10)+(ch^48),ch=getchar();
	x=(f?-x:x);a=x;qread(b...);
}
template<class T1,class T2>inline T1 qmax(const T1 &x,const T2 &y){return x>y?x:y;}
template<class T1,class T2>inline T1 qmin(const T1 &x,const T2 &y){return x<y?x:y;}
int n,m,a[MAXN][MAXN],dp[MAXN][MAXN][257],f[MAXN][MAXN],ans=-inf;
inline int get_sum(int a1,int b1,int a2,int b2){return f[a2][b2]-f[a1-1][b2]-f[a2][b1-1]+f[a1-1][b1-1];}
inline int sum(int a1,int b1,int k){return get_sum(a1-k,b1-k,a1+k,b1+k);} // 计算正方形数字和
int main()
{
	qread(n,m);int i,j,k;for(i=1;i<=n;i++) for(j=1;j<=m;j++) qread(a[i][j]);
	for(i=1;i<=n;i++) for(j=1;j<=m;j++) f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j]; // 二维前缀和
	for(i=1;i<=n;i++) for(j=1;j<=m;j++) dp[i][j][0]=a[i][j]; // 初始化,每个边长为1的螺旋形的数字和都是所在格子的数
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			int t=qmin(i-1,qmin(j-1,qmin(n-i,m-j))); // 最大边长
			for(k=1;k<=t;k++) dp[i][j][k]=sum(i,j,k)-dp[i][j][k-1]-a[i-k+1][j-k],ans=qmax(ans,dp[i][j][k]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-02-17 19:46  l_x_y  阅读(34)  评论(0编辑  收藏  举报