这题目虽然不算难,但我确实理解了很长时间才搞明白做法(我太菜了,哭

题目要求在规定范围内给定炸弹位置和价值,求出半径为r的正方形能框出的总价值最大为多少。

首先,是对题目中“若目标位于爆破正方形的边上,该目标将不会被摧毁。”的理解,考虑到正方形框可以左右上下移动<<1的距离,即可将原本处于边上的炸弹框入,因此在之后的解题过程中可以直接忽略此句话。
其次,考虑如何表示出正方形框内的价值。显然要用到二维的前缀和思路,将范围内的所有点所代表的前缀和先扫一遍,存在数组中。
图片说明
如图算法即可表示出v[i][j]+=v[i-1][j]+v[i][j-1]-v[i-1][j-1]。
之后,再以正方形的右上角的点的坐标用一遍循环,计算方式同上前缀和,即可求出最大价值。

程序主要须注意两点:
1、数组稍微开大一些,一般比要用的多开10左右,另外数组较大的话将声明写在主程序外。
2、注意到整个范围是由0开始的,公式里又有-1,为了避免分类讨论,在读入坐标时,直接将x、y都加一,构造出由1到5001的范围,这样循环中的i,j就可以从1开始,而不用担心出错。

完整代码:
#include<bits/stdc++.h>
using namespace std;
int v[5010][5010]={0};
int main()
{
int n,r,xx,yy,i,x,y,w,j,maxn;
scanf("%d%d",&n,&r);
xx=r;
yy=r;
for (i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&w);
x++;
y++;
v[x][y]=w;
xx=max(x,xx);
yy=max(y,yy);
}
for (i=1;i<=xx;i++)
{
for (j=1;j<=yy;j++)
v[i][j]+=v[i-1][j]+v[i][j-1]-v[i-1][j-1];
}
maxn=0;
for (i=r;i<=xx;i++)
{
for (j=r;j<=yy;j++)
maxn=max(maxn,v[i][j]-v[i-r][j]-v[i][j-r]+v[i-r][j-r]);
}
printf("%d",maxn);
return 0;
}