NC20032 HNOI2003 激光炸弹

题目

牛客网

思路

5001*5001,量太大了,直接用前缀和

整一个5001*5001的二维数组来对应整个地图,数组中的元素表示当前坐标上目标的价值(无目标即为0)

先很普通的用循环记录每个目标的坐标和价值,然后再循环计算前缀和。
计算时,每个点[i][j]上记录的价值和[ i ][ j ]+[ i-1 ][ j ]+[ i ][ j-1 ]-[ i-1 ][ j-1 ] 在这里插入图片描述

因为炸弹无法破坏爆炸范围边界上的目标,所以爆炸范围为R的炸弹最多一次可以炸掉R*R个目标(画个图把范围左右移动一下就明白了),我们在计算被破坏的目标的价值和时一样用到容斥原理,[ i ][ j ]-[ i-R ][ j ]-[ i ][ j-R ]+[ i-R ][ j-R ] ,然后记录最大值就可以了

代码

#include<iostream>

using namespace std;
int map[5001][5001] = {0};//二维地图上目标的价值
int main() {
    int n;  //地图上目标的个数
    int R;  //爆破范围正方形的边长
    cin >> n >> R;
    int x, y, v;  //目标的坐标和价值
    int boardX = 0, boardY = 0;
    //输入目标坐标和价值,同时计算前缀和
    for (int i = 0; i < n; ++i) {
        cin >> x >> y >> v;
        map[x][y] = v;
        //记录一下离原点最远的目标的位置,方便提前结束循环缩短运行时间
        if (x > boardX)boardX = x;
        if (y > boardY)boardY = y;
    }
    //计算前缀和
    for (int i = 0; i <= boardX; ++i) {
        for (int j = 0; j <= boardY; ++j) {
            if (i > 0)map[i][j] += map[i - 1][j];
            if (j > 0)map[i][j] += map[i][j - 1];
            if (i > 0 && j > 0)map[i][j] -= map[i - 1][j - 1];
        }
    }
    int maxValue = 0; //一次能炸掉的总价值的最大值
    for (int i = 0; i <= boardX; ++i) {
        for (int j = 0; j <= boardY; ++j) {
            int value = map[i][j];  //这次能炸掉的总价值
            if (i >= R)value -= map[i - R][j];
            if (j >= R)value -= map[i][j - R];
            if (i >= R && j >= R)value += map[i - R][j - R];
            if (value > maxValue)maxValue = value;
        }
    }
    cout << maxValue;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值