Two-dimensional prefix sum-laser problem Acwing99

Laser problem

Problem:
There are N targets on the map. Use integers Xi, Yi to represent the position of the target on the map. Each target has a value Wi.

Note: Different targets may be in the same location.

There is now a new type of laser bomb that can destroy all targets in a square containing R×R positions.

The launch of the laser bomb is located by satellite, but it has a disadvantage that its explosion range, that is, the sides of the square must be parallel to the x and y axes.

What is the maximum value of the target on the map that can be destroyed by a bomb.

Input format
Enter the positive integers N and R in the first line, which represent the number of targets on the map and the side length of the square, respectively. The data are separated by spaces.

In the next N lines, enter a set of data in each line. Each set of data includes three integers Xi, Yi, Wi, which represent the x-coordinate, y-coordinate and value of the target, and the data are separated by spaces.

Output format
Output a positive integer, which represents the total value of a bomb that can blow up the target on the map.

Data range
0≤R≤10^9
0<N≤10000,
0≤Xi,Yi≤5000
0≤Wi≤1000
Input example:
2 1
0 0 1
1 1 1
Output example:
1

This question is a two-dimensional prefix and question worth thinking about. Ingenious thinking, the situation with (x, y) as the explosion center is transferred to (x, y) as the lower right corner to think about the overall situation at the upper left. This idea may appear in prefix sum and dynamic programming.

/*
求一个矩形范围的总价值,由此可以想到求前缀和降低复杂度
若每个范围的总价值用暴力求解 m 次 时间复杂度为 O( m * N ^ 2 )
使用前缀和时间复杂度为 O(N ^ 2)
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 5050;//点的坐标最大为5000
int f[N][N];//记录输入时每个点的总价值,同时也是二维前缀和数组——记录以(x, y)为右下角范围的前缀和。

int main(){
    
    
    memset(f, 0,sizeof(f));//初始化数组
    int N , R;//N 为目标数,R为炸弹轰炸的边长
    cin >> N >> R;
    int n = R , m = R;//n, m分别为炸弹爆炸点的右下角边界
    for(int i = 0 ,x, y,w;i < N ;i++){
    
    
        cin >> x >> y >> w;//(x,y)上有价值为w的目标
        x++, y++;//从1 ~ N 则前缀和不必要处理边界问题
        n = max(n ,x);
        m = max(m ,y);//更新边界
        f[x][y] += w;//更新该点的总价值
    }
    for(int i = 1; i <= n;i++){
    
    
        for(int j = 1; j <= m;j++){
    
    
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];//求取前缀和
        }
    }
    
    int ans = 0;//记录最大价值
    for(int i = R ;i <= n;i ++){
    
    
        for(int j = R ;j <= m ;j++){
    
    
            //将爆炸中心点转移至以(i, j)为右下的最上方爆炸范围处理。便于处理边长为奇数时的情况
            ans = max(ans, f[i][j] - f[i - R][j] - f[i][j - R] + f[i - R][j - R]);
        }
    }
    cout << ans << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45830383/article/details/108679995