【算法競賽刷題模板15】【二維數組前綴和】

【算法競賽刷題模板15】【二維數組前綴和】


0.總結

Get to the points first. The article comes from LawsonAbs!
  • 二維數組前綴和
  • 容斥原理

下面結合一道例題【洛谷】P2280 [HNOI2003]激光炸彈,來講講如何實現二維數組的前綴和。

1.題意

二維座標中每個點都有一定的價值。求出座標系中以某點作爲邊長m的正方形的右下角的最大價值。

2.思想

二維數組前綴和

  • 這裏的前綴指的是從(0,0)(x,y)這個矩形區域,其和就是 s[x][y]
  • 前綴和的推導公式
    s[i][j] = s[i-1][j] + s[i][j-1]- s[i-1][j-1] + val[i][j],其中s[0][j]s[i][0]需要單獨判斷

如果用圖形表示的話,則是下面這個樣子
s[i][j] =
在這裏插入圖片描述
s[i][j] =
在這裏插入圖片描述
s[i-1][j] =
在這裏插入圖片描述
s[i-1][j-1]=
在這裏插入圖片描述
val[i][j]=
在這裏插入圖片描述

綜合表述,也就是下面這個樣子:
在這裏插入圖片描述
棕色是綠色和紫色的重合部分。

  • 在得到前綴和的基礎上,針對題目要求適當變形即可

3.代碼

#include<iostream>
using namespace std;
const int X = 5005,Y = 5005,N = 5005;
int s[N][N];//二維數組前綴和 
int res = 0;
int main(){
	int n,m;
	cin >> n>> m;
	int a,b,w,mx=0,my=0;
	for(int i =0;i < n;i++){
		cin >> a >> b >> w ;
		mx=max(mx,a);//求出座標的最大值 
		my=max(my,b);
		s[a][b]+=w;//爲節省空間,直接累加 
	}
	
	//1.計算前綴和 
	//01.單獨計算s[0][j], s[i][0]
	//02.計算s[i][j] 	
	for(int i = 1;i<= max(mx,my);i++){
		s[i][0] = s[i-1][0] + s[i][0];
		s[0][i] =s[0][i-1] +  s[0][i];
	} 
	for(int i= 1;i<=max(mx,my);i++){
		for(int j = 1;j<=max(mx,my);j++){
			//因爲s[i][j]尚未計算過,所以可以累加 
			s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1] ; 
		}
	}
	
	//2.計算m個正方形內的和,以(i,j)爲正方形的右下角
	//01.如果枚舉左上角,則需要特判邊界處理,所以更優的方法是枚舉右下角 
	//02.注意這裏的i,j的上限是max(mx,my),否則當m>mx時,就會出現問題。 
	for(int i = m-1;i<=max(mx,my);i++){
		for(int j = m-1;j<=max(mx,my);j++){
			int temp = s[i][j]
						- (j-m<0 ? 0: s[i][j-m]) //防止下標越界&簡潔,用三元運算符 
						- (i-m<0 ? 0: s[i-m][j])
			 			+ ((i-m<0 || j-m<0)? 0:s[i-m][j-m]);
			res = max(res,temp);
		}
	} 
	cout << res <<"\n";
} 

測試用例

1 3
0 1 0

2 1
0 0 1
1 1 1

2 1
0 0 1
1 2 3

3 1
0 0 1
1 2 3
0 1 4

3 2
0 0 1
1 2 3
0 1 4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章