题目描述
一种新型的激光炸弹,可以摧毁一个边长为 mm 的正方形内的所有目标。现在地图上有 nn 个目标,用整数 x_ixi , y_iyi 表示目标在地图上的位置,每个目标都有一个价值 v_ivi .激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为 mm 的边必须与 xx 轴, yy 轴平行。若目标位于爆破正方形的边上,该目标不会被摧毁。
现在你的任务是计算一颗炸弹最多能炸掉地图上总价值为多少的目标。
输入格式
输入的第一行为整数 nn 和整数 mm,
接下来的 nn 行,每行有 33 个整数 x, y, vx,y,v,表示一个目标的坐标与价值。
输出格式
输出仅有一个正整数,表示一颗炸弹最多能炸掉地图上总价值为多少的目标(结果不会超过 3276732767 )。
输入输出样例
输入 #1复制
2 1 0 0 1 1 1 1
输出 #1复制
1
说明/提示
数据规模与约定
- 对于 100\%100% 的数据,保证 1 \le n \le 10^41≤n≤104,0 \le x_i ,y_i \le 5\times 10^30≤xi,yi≤5×103,1 \le m \le 5\times 10^31≤m≤5×103,1 \le v_i < 1001≤vi<100。
首先需要了解二维前缀和的概念:
二维数组前缀(利用图形的面积进行理解):
每个点(x,y)所代表的值均为(x,y)到(1,1)所构成四边形区域的权值
————————————————————————————————
这里推荐一个博主的讲解:
原文链接:https://blog.csdn.net/qq_34990731/article/details/82807870
理解了二维前缀和的概念,这题就相对简单了
放上源码:
import java.io.*;
public class 前缀和 {
public static void main(String[] args) throws IOException {
StreamTokenizer r = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
r.nextToken();
int n = (int) r.nval;
r.nextToken();
int m = (int) r.nval;
int sum = 0;
int maxHight = 0;
int maxWide = 0;
int a[][] = new int[5010][5010];
for (int i = 0; i < n; i++) {
r.nextToken();
int x = (int) r.nval;
r.nextToken();
int y = (int) r.nval;
r.nextToken();
int v = (int) r.nval;//v值
a[x+1][y+1]=v;
//找到最大边界处
maxHight = maxHight >= x ? maxHight : x;
maxWide = maxWide >= y ? maxWide : y;
}
//因为数组扩展了一圈,故极小历遍范围+1
maxHight++;
maxWide++;
//对数组进行前缀处理,其坐标(x,y)处值的含义为点(x,y)处到(1,1)区域所包含的权值
for (int i = 1; i <a.length ; i++) {
for (int j = 1; j < a.length; j++) {
a[i][j] +=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
int boomHight = m <= maxHight ? m : maxHight ;
int boomWide = m <= maxWide ? m : maxWide ;
int i = boomHight, j = boomWide;
获得轰炸区,若轰炸区范围大于极小历遍区的边界,则限制
while (true) {
//tempSum代表点(i,j)到点(i-boomHigh,j-boomWide)区间范围的全职(即不同点轰炸区所包括的权值)
int tempSum = a[i][j]+a[i-boomHight][j-boomWide]-a[i-boomHight][j]-a[i][j-boomWide];
sum = sum >= tempSum ? sum : tempSum;
j++;
if (j == maxWide + 1 && i == maxHight) {
break;
}
if (j > maxWide ) {
i++;
j = boomWide;
}
}
pr.println(sum);
pr.flush();
}
}