Ac Wing 99.激光炸弹(大白话详解版)

[题目概述]

地图上有 N个目标,用整数 X i X_i Xi, Y i Y_i Yi表示目标在地图上的位置,每个目标都有一个价值 W i W_i Wi

注意:不同目标可能在同一位置。

现在有一种新型的激光炸弹,可以摧毁一个包含 R×R个位置的正方形内的所有目标。激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 x,y轴平行。求一颗炸弹最多能炸掉地图上总价值为多少的目标。

输入格式

第一行输入正整数 N和 R,分别代表地图上的目标数目和正方形包含的横纵位置数量,数据用空格隔开。接下来 N行,每行输入一组数据,每组数据包括三个整数 X i X_i Xi, Y i Y_i Yi, W i W_i Wi,分别代表目标的 x坐标,y坐标和价值,数据用空格隔开。

输出格式

输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。

数据范围

0≤ R ≤ 1 0 9 10^9 109

0< N ≤10000
,
0≤ X i X_i Xi, Y i Y_i Yi ≤5000

0≤ W i W_i Wi ≤1000

输入样例:
2 1
0 0 1
1 1 1
输出样例:
1
  • 分析题目
    在一个大网格中,部分格点具有价值,一个炸弹可以摧毁 R×R 个格点,问摧毁的格点总价值最大是多少,读完题很容易能判断出用二维前缀和来解,基本思路就是以正方形右下角来进行枚举求出前缀和,再求最大值 。在这其中有很多小细节

    • x,y范围最大就到5000,那么R如果很大,其实没有什么意义,所以
        R = min(5001, R);
    
    • 在学习前缀和时,我们都是从1开始枚举,而这里的x y 是从0开始,所以
    	int x, y, w;
    	cin >> x >> y >> w;
    	x++, y++;
    
    • 在判断最大值时,因为我们枚举的是正方形的右下角,所以应该从R开始枚举
    	for (int i = R; i <= n; i++)
    			for (int j = R ; j <= m; j++)
    
    • 最后一点就是预处理前缀和、求前缀和时的角标问题
      Ac Wing 99.激光炸弹(大白话详解版)_第1张图片
  • 完整代码
    上面未提及的有注释

#include 
#include 
#include 
using namespace std;
const int N = 5005; // 习惯性多开5个
int n, m; // 求输入的x y 的最大值,确定预处理前缀和的范围
int s[N][N];

int main() {
	int cnt, R;
	cin >> cnt >> R;
	R = min(5001, R);
	n = m = R;
	
	while (cnt--) {
		int x, y, w;
		cin >> x >> y >> w;
		x++, y++; // 将x y整体加1
		n = max(x, n), m = max(m, y);
		s[x][y] += w;
	}

	//预处理前缀和
	//求出所有位置的前缀和
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
			
	int res = 0;
	//枚举所有边长是R的矩形,(i,j)为右下角
	for (int i = R; i <= n; i++)
		for (int j = R ; j <= m; j++)
			res = max(res, s[i][j] - s[i - R][j] - s[i][j - R] + s[i - R][j - R]);
	cout << res << endl;
	return 0;
}
  • 本题就结束了,还有什么问题可以在评论区留言,别忘了点赞收藏哟!

你可能感兴趣的:(算法,c++,数据结构)