Description
一种新型的激光炸弹,可以摧毁一个边长为R的正方形内的所有的目标。现在地图上有n(N<=10000)个目标,用整数Xi,Yi(其值在[0,5000])表示目标在地图上的位置,每个目标都有一个价值。激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为R的正方形的边必须和x,y轴平行。若目标位于爆破正方形的边上,该目标将不会被摧毁。 0
Input
输入文件的第一行为正整数n和正整数R,接下来的n行每行有3个正整数,分别表示
Output
输出文件仅有一个正整数,表示一颗炸弹最多能炸掉地图上总价值为多少的目标(结果不会超过32767)。
标准做法是什么呢?不论。我们钻个 空子,用5000^2的二维前缀和把它过了。
二维前缀和的概念:
如图,蓝点的f[x][y]表示从底部(0,0)到(x,y)的所有区间的和。
其计算方法是:
f[x][y]=f[x][y]-f[x-1][y]-f[x][y-1]+f[x-1][y-1]
本题真正恶心的是他的边界问题,即若目标位于爆破正方形的边上,该目标将不会被摧毁。
于是我多开了一位,并且加了边界处理。
代码:
#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
long ans;
long f[5002][5002],x,y,z,i,n,r,j;
int main()
{
scanf("%ld %ld",&n,&r);
memset(f,0,sizeof(f));
if (r==0){printf("0");return 0;}
for (i=1;i<=n;i++)
{
scanf("%ld %ld %ld",&x,&y,&z);x++;y++;
f[x][y]=z;
}
ans=f[1][1];
for (i=2;i<=5001;i++)
{
ans=max(f[1][i],ans);
ans=max(f[i][1],ans);
f[1][i]+=f[1][i-1];
f[i][1]+=f[i-1][1];
}
for (i=2;i<=5001;i++)
for (j=2;j<=5001;j++)
{
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
if (i>=r&&j>=r) ans=max(ans,f[i][j]-f[i-r][j]+f[i-r][j-r]-f[i][j-r]);
};
printf("%ld\n",ans);
scanf("%ld %ld",&n,&r);
return 0;
}