【二维前缀和】洛谷P2280 激光炸弹

链接

https://www.luogu.org/problemnew/show/P2280

大意

最大子矩阵和

给定边长至多为5000的矩阵,共有 n 个点有价值,求出边长为 R 的价值和最大的子矩阵

思路

二维前缀和
s [ i ] [ j ] 表示以第一行第一个格子为左上角,长宽分别为 i j 所构成的子矩阵中所有元素之和

可以得到方程:

s [ i ] [ j ] = a [ i ] [ j ] + s [ i 1 ] [ j ] + s [ i ] [ j 1 ] s [ i 1 ] [ j 1 ]

至于为什么要减,是利用了容斥原理,去掉重复的

代码

#include<cstdio>
using namespace std;
int x,y,w,n,R,maxx=5001,maxy=5001,s[5005][5005],ans;
signed main()
{
    scanf("%d%d",&n,&R);
    for(register int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&x,&y,&w);
        x++;y++;
        s[x][y]=w;
    }
    for(register int i=1;i<=maxx;i++)
     for(register int j=1;j<=maxy;j++)
      s[i][j]=s[i][j]+s[~-i][j]+s[i][~-j]-s[~-i][~-j];//转移
    for(register int i=0;i<=maxx-R;i++)
     for(register int j=0;j<=maxy-R;j++)
      if(s[i][j]-s[i+R][j]-s[i][j+R]+s[i+R][j+R]>ans) ans=s[i][j]-s[i+R][j]-s[i][j+R]+s[i+R][j+R];//求值
    printf("%lld",ans);//输出
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/81623834