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]$。
当然这道题有两个点需要注意:
- 目标点坐标范围为$[0,5000]$,可能会取到$0$,造成数组越界。对此我们只需要在将横、纵坐标均加$1$即可。
- 这道题有卡空间。所以可以只开$s$数组,并累加即可。
#include<bits/stdc++.h> #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; }