前缀和-AcWing 99-激光炸弹
题目:
一种新型的激光炸弹,可以摧毁一个边长为 R 的正方形内的所有的目标。
现在地图上有 N 个目标,用整数Xi,Yi表示目标在地图上的位置,每个目标都有一个价值Wi。
激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个边长为 R 的正方形的边必须和x,y轴平行。
若目标位于爆破正方形的边上,该目标不会被摧毁。
求一颗炸弹最多能炸掉地图上总价值为多少的目标。
输入格式
第一行输入正整数 N 和 R ,分别代表地图上的目标数目和正方形的边长,数据用空格隔开。
接下来N行,每行输入一组数据,每组数据包括三个整数Xi,Yi,Wi,分别代表目标的x坐标,y坐标和价值,数据用空格隔开。
输出格式
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。
数据范围
0≤R≤109
0<N≤10000,
0≤Xi,Yi≤5000
0≤Wi≤1000
输入样例:
2 1
0 0 1
1 1 1
输出样例:
1
题意:
在 一 个 点 阵 中 有 N 个 目 标 , 一 个 炸 弹 可 以 摧 毁 的 区 域 是 边 长 为 R 的 正 方 形 。 在一个点阵中有N个目标,一个炸弹可以摧毁的区域是边长为R的正方形。在一个点阵中有N个目标,一个炸弹可以摧毁的区域是边长为R的正方形。
输 入 目 标 数 量 N , 正 方 形 边 长 R 。 输入目标数量N,正方形边长R。输入目标数量N,正方形边长R。
输 入 N 个 目 标 的 坐 标 X i , Y i , 以 及 它 们 的 价 值 W i 。 输入N个目标的坐标X_i,Y_i,以及它们的价值W_i。输入N个目标的坐标Xi,Yi,以及它们的价值Wi。
输 出 一 个 炸 弹 可 摧 毁 的 最 大 价 值 。 输出一个炸弹可摧毁的最大价值。输出一个炸弹可摧毁的最大价值。
题解:
点 阵 中 , 长 度 为 R 的 线 段 最 多 可 以 包 含 R + 1 个 点 , 但 由 于 边 界 的 点 是 炸 不 到 的 , 所 以 边 长 为 R 的 正 方 形 最 多 可 以 包 含 的 点 的 个 数 是 R × R 。 点阵中,长度为R的线段最多可以包含R+1个点,但由于边界的点是炸不到的,\\所以边长为R的正方形最多可以包含的点的个数是R×R。点阵中,长度为R的线段最多可以包含R+1个点,但由于边界的点是炸不到的,所以边长为R的正方形最多可以包含的点的个数是R×R。
问 题 可 以 转 化 为 求 R × R 的 二 维 矩 阵 和 的 最 大 值 。 问题可以转化为求R×R的二维矩阵和的最大值。问题可以转化为求R×R的二维矩阵和的最大值。
采 用 二 位 前 缀 和 来 处 理 。 采用二位前缀和来处理。采用二位前缀和来处理。
前 缀 和 公 式 : s u m [ i ] [ j ] = s u m [ i − 1 ] [ j ] + s u m [ i ] [ j − 1 ] − s u m [ i − 1 ] [ j − 1 ] + A [ i ] [ j ] 前缀和公式:sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+A[i][j]前缀和公式:sum[i][j]=sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1]+A[i][j]
对 于 R × R 的 矩 阵 , 设 矩 阵 的 右 下 顶 点 为 i , j , 则 左 上 顶 点 为 i − R + 1 和 j − R + 1 。 对于R×R的矩阵,设矩阵的右下顶点为i,j,则左上顶点为i-R+1和j-R+1。对于R×R的矩阵,设矩阵的右下顶点为i,j,则左上顶点为i−R+1和j−R+1。
点 ( i − R + 1 , j − R + 1 ) 和 点 ( i , j ) 构 成 的 边 长 为 R 的 矩 阵 前 缀 和 为 : s u m [ i ] [ j ] − s u m [ i − R ] [ j ] − s u m [ i ] [ j − R ] + s u m [ i − R ] [ j − R ] , 求 其 最 大 值 即 可 。 点(i-R+1,j-R+1)和点(i,j)构成的边长为R的矩阵前缀和为:sum[i][j]-sum[i-R][j]-sum[i][j-R]+sum[i-R][j-R],求其最大值即可。点(i−R+1,j−R+1)和点(i,j)构成的边长为R的矩阵前缀和为:sum[i][j]−sum[i−R][j]−sum[i][j−R]+sum[i−R][j−R],求其最大值即可。
由 上 式 可 得 , i − R > = 0 即 i > = R , j − R > = 0 , j > = R 。 i 和 j 的 最 小 值 为 R , 并 且 根 据 数 据 范 围 可 知 , 当 R > = 5001 时 都 可 以 包 含 整 个 点 阵 。 所 以 R 取 m i n ( 5001 , R ) 。 由上式可得,i-R>=0即i>=R,j-R>=0,j>=R。i和j的最小值为R,\\并且根据数据范围可知,当R>=5001时都可以包含整个点阵。所以R取min(5001,R)。由上式可得,i−R>=0即i>=R,j−R>=0,j>=R。i和j的最小值为R,并且根据数据范围可知,当R>=5001时都可以包含整个点阵。所以R取min(5001,R)。
另 外 , 由 于 原 数 组 A 在 求 完 前 缀 和 数 组 s u m 以 后 就 不 再 使 用 , 所 以 考 虑 使 用 一 个 数 组 优 化 空 间 。 则 s u m [ i ] [ j ] + = s u m [ i − 1 ] [ j ] + s u m [ i ] [ j − 1 ] − s u m [ i − 1 ] [ j − 1 ] 。 另外,由于原数组A在求完前缀和数组sum以后就不再使用,所以考虑使用一个数组优化空间。\\则sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]。另外,由于原数组A在求完前缀和数组sum以后就不再使用,所以考虑使用一个数组优化空间。则sum[i][j]+=sum[i−1][j]+sum[i][j−1]−sum[i−1][j−1]。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=5e3+5;
int N,R;
int n,m;//矩阵的行列边界
int sum[maxn][maxn];
int main()
{
cin>>N>>R;
n=m=R;///n>=R
for(int i=0;i<N;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
x++,y++;
n=max(n,x),m=max(m,y);
sum[x][y]+=w;
}
for(int i=1;i<=n;i++)//前缀和
for(int j=1;j<=m;j++)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
int ans=0;
for(int i=R;i<=n;i++)
for(int j=R;j<=m;j++)
ans=max(ans,sum[i][j]-sum[i-R][j]-sum[i][j-R]+sum[i-R][j-R]);
printf("%d\n",ans);
return 0;
}