2次元プレフィックス合計レーザー問題Acwing99

レーザーの問題

問題:
マップ上にN個のターゲットがあります。整数Xi、Yiを使用して、マップ上のターゲットの位置を表します。各ターゲットの値はWiです。

注:異なるターゲットが同じ場所にある場合があります。

R×Rの位置を含む正方形のすべてのターゲットを破壊できる新しいタイプのレーザー爆弾があります。

レーザー爆弾の発射は衛星によって行われますが、その爆発範囲、つまり正方形の側面がx軸とy軸に平行でなければならないという欠点があります。

爆弾によって破壊される可能性のあるマップ上のターゲットの最大値はいくつですか。

入力形式
最初の行に正の整数NとRを入力します。これらは、それぞれマップ上のターゲットの数と正方形の辺の長さを表します。データはスペースで区切られます。

次のN行に、各行にデータのセットを入力します。各データのセットには、ターゲットのx座標、y座標、および値を表す3つの整数Xi、Yi、Wiが含まれ、データは次のように区切られます。スペース。

出力形式
正の整数を出力します。これは、マップ上のターゲットを爆破する可能性のある爆弾の合計値を表します。

データ範囲
0≤R≤10^ 9
0 <N≤10000、
0≤Xi、Yi≤5000
0≤Wi≤1000の
入力例:
2 1
0 0 1
1 1 1
出力例:
1

この質問は、2次元の接頭辞であり、検討する価値のある質問です。独創的な思考、爆発の中心としての(x、y)の状況を右下隅の(x、y)に転送して、左上の全体的な状況を考えます。このアイデアは、接頭辞の合計と動的計画法に現れる可能性があります。

/*
求一个矩形范围的总价值,由此可以想到求前缀和降低复杂度
若每个范围的总价值用暴力求解 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;
}

おすすめ

転載: blog.csdn.net/qq_45830383/article/details/108679995