dp46道有类似题 上下左右分别dp一次然后求出以每个点为鞍点的最大上下左右左边界的矩形,然后求里面所有包含这个鞍点的所有子矩形的面积和
求子矩形的面积和公式比较难吧数学太菜
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
#define mod (1ll<<32)
LL mp[1005][1005],n,m,L[1005][1005],R[1005][1005],D[1005][1005],U[1005][1005],t;
int main()
{
scanf("%I64d",&t);
while(t--)
{
LL ans = 0;
scanf("%I64d%I64d",&n,&m);
for(int i=1;i<=n;i++){mp[i][0] = -1;mp[i][m+1] = -1;}
for(int i=1;i<=m;i++){mp[0][i] = 100000000ll;mp[n+1][i] = 100000000ll;}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%I64d",&mp[i][j]);
L[i][j] = j;
R[i][j] = j;
U[i][j] = i;
D[i][j] = i;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
while(mp[i][j]<mp[i][L[i][j]-1])L[i][j] = L[i][L[i][j]-1];
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
while(mp[i][j]<mp[i][R[i][j]+1])R[i][j] = R[i][R[i][j]+1];
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
while(mp[j][i]>mp[U[j][i]-1][i])U[j][i] = U[U[j][i]-1][i];
for(int i=1;i<=m;i++)
for(int j=n;j>=1;j--)
while(mp[j][i]>mp[D[j][i]+1][i])D[j][i] = D[D[j][i]+1][i];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
LL a = R[i][j]-j+1,b = j-L[i][j]+1,c = D[i][j]+1-i,d = i-U[i][j]+1;
LL row = a*(a+1)/2*b+b*(b-1)/2*a,col = c*(c+1)/2*d+d*(d-1)/2*c;
ans+=row*col%mod*mp[i][j];
ans%=mod;
}
printf("%I64d\n",ans);
}
return 0;
}
本文介绍了一种使用动态规划解决寻找矩阵中以每个点为鞍点的最大上下左右边界矩形的问题,并计算这些矩形的面积总和。通过四个方向的DP预处理,实现了高效查找。
380

被折叠的 条评论
为什么被折叠?



