Luogu P2280/ACAG 0x03-1 激光炸弹

Luogu P2280/ACAG 0x03-1 激光炸弹

这道题要用到二维前缀和。
首先读入时,令$a[x][y]=val$;
然后不难递推出$s[i][j]=s[x-1][y]+s[i][j-1]-s[i-1][j-1]+a[i][j]$。
此处运用了容斥原理。
然后再遍历答案,不难得到,对于以$(x,y)$为右下角的格子,所得的价值为:$s[x][y]-s[x-r][y]-s[x][y-r]+s[x-r][y-r]$。
当然这道题有两个点需要注意:

  1. 目标点坐标范围为$[0,5000]$,可能会取到$0$,造成数组越界。对此我们只需要在将横、纵坐标均加$1$即可。
  2. 这道题有卡空间。所以可以只开$s$数组,并累加即可。
#include
#define N 5010

using namespace std;

int n,r,ans;
int s[N][N];

int Calc(int x,int y) {
    return s[x][y]-s[x-r][y]-s[x][y-r]+s[x-r][y-r];
}

void Read() {
    scanf("%d%d",&n,&r);
    for(int i=1;i<=n;i++) {
        int x,y,val;
        scanf("%d%d%d",&x,&y,&val);
        s[x+1][y+1]=val;
    }
    return;
}

void Solve() {
    for(int i=1;i<=5001;i++) {
        for(int j=1;j<=5001;j++) {
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        }
    }
    for(int i=r;i<=5001;i++) {
        for(int j=r;j<=5001;j++) {
            ans=max(ans,Calc(i,j));
        }
    }
    printf("%d",ans);
    return;
}

int main()
{
    Read();
    Solve();
    return 0;
}

你可能感兴趣的:(Luogu P2280/ACAG 0x03-1 激光炸弹)