激光炸弹(二维前缀和 + 模拟 + 暴力)

激光炸弹

题目描述:

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

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

现在有一种新型的激光炸弹,可以摧毁一个包含 R × R R \times R R×R个位置的正方形内的所有目标。

激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 x , y x, y x,y轴平行。

求一颗炸弹最多能炸掉地图上总价值为多少的目标。

输入格式:

第一行输入正整数 N 和 R N 和 R NR,分别代表地图上的目标数目和正方形的边长,数据用空格隔开。

接下来 N N N 行,每行输入一组数据,每组数据包括三个整数 X i , Y i , W i X_i,Y_i,W_i Xi,Yi,Wi,分别代表目标的 x x x 坐标, y y y坐标和价值,数据用空格隔开。

输出格式:

0 ≤ R ≤ 109 0≤R≤109 0R109
0 < N ≤ 10000 , 0<N≤10000, 0<N10000,
0 ≤ X i , Y i ≤ 5000 0≤X_i,Y_i≤5000 0Xi,Yi5000
0 ≤ W i ≤ 1000 0≤W_i≤1000 0Wi1000

AC 代码:

/*
1、注意,这里的每个目标的坐标都是整数,那么我们可以用一个方框的
的左上角的那个点代表这个方框的权值
2、在正常情况下,边长为 R 的正方形能覆盖的很显然是 (R + 1) * (R + 1)个
但是由于题目中边缘上的点不在摧毁范围内,那么,边长为 R的正方形就只能摧毁
R * R 个点,因此,只有边长为 R + 1, 才能摧毁全部的点
3、对于 R,我们做一下,如果 R 过大的话,即 R 超过了 x, y(x,y的坐标都是最大为5000)
那么,其实 R只能取 5001,因为如果 R 取太大,比如 100000,在最后一个循环中,就会出现不进行
循环的情况
 */
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 5010;

int s[N][N];

int main()
{
    
    
	int n, R;
	cin >> n >> R;		
	R = min(R, 5001);				// R的最大值为5001
	
	for (int i = 0; i < n; i ++)	// 赋予数组权重
	{
    
    
		int x, y, w;
		cin >> x >> y >> w;
		s[++ x][++ y] += w;			// 由于题目的坐标是从 1 开始,因此我们应当加 1
	}
	
	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];
	
	int res = 0;
	for (int i = R; i <= 5001; i ++)// 直接将边长为 R 的正方形进行一格一格移动,得到最大值即可
		for (int j = R; j <= 5001; 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_57095511/article/details/121216133