一种新型的激光炸弹,可以摧毁一个边长为m的正方形内的所有目标。现在地图上有n个目标,用整数xi,yi表示目标在地图上的位置,每个目标都有一个价值vi激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为m的边必须与x轴, y轴平行。若目标位于爆破正方形的边上,该目标不会被摧毁。
现在你的任务是计算一颗炸弹最多能炸掉地图上总价值为多少的目标。
x,y的范围是5000,r是
思路:
很明显的二维前缀和求最值问题;
二维前缀和的推导:
求从[i1,j1] 到 [i2,j2] 的子矩阵的和:
+
-
这道题又说明在边长为r的方形边缘无法取到,那么以每个方格为一个点,取边长为求r的矩形的前缀和,然后枚举他的右下端点,取最大值即可:
边长为r 事实上是[ i-r+1,j-r+1] ~ [i,j] 的前缀和
即
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5010;
int s[N][N];
int n,r;
int main()
{
cin>>n>>r;
r=min(r,5001);
while(n--)
{
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
a++,b++; //下标从[1,1]开始方便处理前缀和
s[a][b]+=w;
}
//这里是1~5001边长是5000
for(int i=1;i<=5001;i++)
for(int j=1;j<=5001;j++)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
int res=0;
for(int i=r;i<=5001;i++)
for(int j=r;j<=5001;j++)
{
//枚举的半径是r-1
int t=s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r];
res=max(res,t);
}
cout<<res<<endl;
return 0;
}