【ACWing】99. 激光炸弹

题目地址:

https://www.acwing.com/problem/content/description/101/

地图上有 N N N个目标,用整数 X i , Y i X_i,Y_i Xi,Yi表示目标在地图上的位置,每个目标都有一个价值 W i W_i Wi。注意:不同目标可能在同一位置。现在有一种新型的激光炸弹,可以摧毁一个包含 R × R R \times R R×R个位置的正方形内的所有目标。激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 x x x y y y轴平行。求一颗炸弹最多能炸掉地图上总价值为多少的目标。

输入格式:
第一行输入正整数 N N N R R R,分别代表地图上的目标数目和正方形包含的横纵位置数量,数据用空格隔开。
接下来 N N N行,每行输入一组数据,每组数据包括三个整数 X i , Y i , W i X_i,Y_i,W_i Xi,Yi,Wi,分别代表目标的 x x x坐标, y y y坐标和价值,数据用空格隔开。

输出格式:
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。数据范围 0 ≤ R ≤ 1 0 9 0≤R≤10^9 0R109 0 < N ≤ 10000 0<N≤10000 0<N10000, 0 ≤ X i , Y i ≤ 5000 0≤X_i,Y_i≤5000 0Xi,Yi5000, 0 ≤ W i ≤ 1000 0≤W_i≤1000 0Wi1000

因为地图最大就是 5001 × 5001 5001\times 5001 5001×5001这么大,所以 R R R最大只能取 5001 5001 5001。这个题目即为求某个矩阵的宽 R R R的子方阵的最大和。可以先求一下二维前缀和,然后暴力枚举子方阵的右下格子的坐标。代码如下:

#include <iostream>
using namespace std;

const int N = 5010;
int g[N][N];
int m, n;

int main() {
  int N, r;
  scanf("%d%d", &N, &r);
  r = min(r, 5001);
  n = m = r;
  for (int i = 0, x, y, w; i < N; i++) {
    scanf("%d%d%d", &x, &y, &w);
    x++, y++;
    g[x][y] += w;
    n = max(n, x), m = max(m, y);
  }

  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];

  int res = 0;
  for (int i = r; i <= n; i++)
    for (int j = r; j <= m; j++)
      res = max(res, g[i][j] - g[i - r][j] - g[i][j - r] + g[i - r][j - r]);
  printf("%d\n", res);
}

时空复杂度 O ( m n ) O(mn) O(mn) m , n m,n m,n为整个地图的长和宽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值