激光炸彈(BZOJ1218)
一種新型的激光炸彈,可以摧毀一個邊長為R的正方形內的所有的目標。現在地圖上有n(N<=10000)個目標,用整數Xi,Yi(其值在[0,5000])表示目標在地圖上的位置,每個目標都有一個價值。激光炸彈的投放是通過衛星定位的,但其有一個缺點,就是其爆破范圍,即那個邊長為R的正方形的邊必須和x,y軸平行。若目標位于爆破正方形的邊上,該目標將不會被摧毀。
輸入輸出格式:
輸入文件的第一行為正整數n和正整數R,接下來的n行每行有3個正整數,分別表示xi,yi,vi
輸出文件僅有一個正整數,表示一顆炸彈最多能炸掉地圖上總價值為多少的目標(結果不會超過32767)。
輸入樣例:
2 1
0 0 1
1 1 1
輸出樣例:
1
分析:
二維數組前綴和:一定區間里價值之和
\(S[i,j] = S[i-1,j] + S[i,j-1]-S[i-1,j-1]+A[i,j]\)
邊長R的正方形的價值(ij為正方形的右下角)
\(P[i,j] = S[i,j] - S[i-R,j] - S[i,j-R] + S[i-R,j-R]\)
然后枚舉正方形右下角找最大值
錯誤題解:(TLE MLE一堆 用于理解)
#include<iostream>
#define N 5000+5
using namespace std;
int A[N][N]={0}; //main函數里定義上限719 X 719
int S[N][N]={0};
int P[N][N]={0};int main(){int n,r,a,b,m;cin>>n>>r;m= 0;while(n--){int x,y,v;cin>>x>>y>>v;A[x][y] = v;if(m<x) m=x;if(m<y) m=y;}m = (m+r>5000)?5000:m+r;for(int i=0;i<m;i++){for(int j=0;j<m;j++){a = (i-1<0)?0:i-1;b = (j-1<0)?0:j-1;S[i][j] = S[a][j]+S[i][b]-S[a][b]+A[i][j];}}int max = 0;for(int i=0;i<m;i++){for(int j=0;j<m;j++){a = (i-r<0)?0:i-r;b = (j-r<0)?0:j-r;P[i][j] = S[i][j] - S[a][j] - S[i][b] + S[a][b];if(P[i][j]>max)max=P[i][j];}}cout<<max;return 0;
}
題解:
#include<iostream>
#define N 5000+5
using namespace std;
int A[N][N]={0}; int main(){int n,r,a,b,c,m;cin>>n>>r;m= 0; // 找個上限 縮短下運行時間while(n--){int x,y,v;cin>>x>>y>>v;A[x+1][y+1] += v;if(m<x) m=x;if(m<y) m=y;}m = (m+r>5000)?5000:m+r;for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){a = (i-1<0)?0:i-1;b = (j-1<0)?0:j-1;A[i][j] += A[a][j]+A[i][b]-A[a][b];}}int max = 0;for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){a = (i-r<0)?0:i-r;b = (j-r<0)?0:j-r;c= A[i][j] - A[a][j] - A[i][b] + A[a][b];if(c>max)max=c;}}cout<<max;return 0;
}