AcWing 99. 激光炸弹
原题链接
简单
作者:
Gabriel.
,
2024-11-01 12:42:56
,
所有人可见
,
阅读 5
思路
求出每个位置坐标对应的子矩阵元素和(代表摧毁目标的总价值),枚举
所有可能的R$\times$R大小的子矩阵,对应元素和最大的那一个即为题目的解
注意
1.不能开两个数组,因为每个数组约是5000x5000这么大,就是5000x5000x4bytes,5000x5000x4/1024/1024=95MB,这题的空间是168MB,所以两个数组会MLE
$\Rightarrow优化:$只保留前缀和数组,先存原矩阵每个位置的值,然后在自身基础上求前缀和$\Leftrightarrow$sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]
2.设定一组坐标变量n、m记录读取到的横纵坐标边界,后续只需在这个范围内遍历所有R边长的矩阵即可找到满足要求的位置,优化了代码时间复杂度
3.R很大时,一定能摧毁所有目标,需要特殊处理一下,否则后续遍历可能无法进行
4.把位置坐标当方格而非点来处理
,便于理解二维前缀和的相关计算公式
代码
#include <bits/stdc++.h>
using namespace std;
int N, R;
int sum[5010][5010];
int ans = 0;
int n, m;
int main()
{
scanf("%d %d", &N, &R);
R = min(R, 5001);
n = m = 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];
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", ans);
return 0;
}