<—点个赞吧QwQ
宣传一下算法提高课整理
地图上有 $N$ 个目标,用整数 $X_{i}, Y_{i}$ 表示目标在地图上的位置,每个目标都有一个价值 $W_i$。
注意:不同目标可能在同一位置。
现在有一种新型的激光炸弹,可以摧毁一个包含 $R \\times R$ 个位置的正方形内的所有目标。
激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 $x,y$ 轴平行。
求一颗炸弹最多能炸掉地图上总价值为多少的目标。
输入格式
第一行输入正整数 $N$ 和 $R$,分别代表地图上的目标数目和正方形的边长,数据用空格隔开。
接下来 $N$ 行,每行输入一组数据,每组数据包括三个整数 $X_{i}, Y_{i}, W_{i}$,分别代表目标的 $x$ 坐标,$y$ 坐标和价值,数据用空格隔开。
输出格式
输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。
数据范围
$0 \le R \le 10^9$
$0 < N \le 10000$,
$0 \le X_{i}, Y_{i} \le 5000$
$0 \le W_i \le 1000$
输入样例:
2 1
0 0 1
1 1 1
输出样例:
1
思路
必看前缀和详解
直接暴力枚举每一个炸的区间在求价值最大值。
代码
#include <iostream>
using namespace std;
const int N = 5010;
int n = 5005,m,r;
int sum[N][N];
int max (int a,int b) {
return a > b ? a : b;
}
int get (int x1,int y1,int x2,int y2) {
return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
}
int main () {
cin >> m >> r;
int maxx,maxy;
for (int i = 1;i <= m;i++) {
int x,y,w;
cin >> x >> y >> w;
x++,y++;
maxx = max (maxx,x);
maxy = max (maxy,y);
sum[x][y] += w;
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= n;j++) sum[i][j] += sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
}
if (r >= maxx && r >= maxy) {
cout << sum[n][n] << endl;
return 0;
}
int ans = 0;
for (int i = 1;i + r - 1 <= n;i++) {
for (int j = 1;j + r - 1 <= n;j++) ans = max (ans,get (i,j,i + r - 1,j + r - 1));
}
cout << ans << endl;
return 0;
}
想问一下这样算 不会超时吗
大佬可以帮忙解释下为什么这里是用这样写吗?
ans = max (ans,get (i,j,i + r - 1,j + r - 1))
我的想法是求前缀和矩阵的子矩阵直接写成:ans = get (i,j,i + r - 1,j + r - 1),但是结果确实有问题,可以帮我解答下吗?
答案要求最大
用前缀和计算的话sum[i][j] 不是会少掉一个[i][j]的价值
请问一下那个倒数第五、六行的i+r-1与j+r-1是什么意思
左上角为(i,j)时右小角的坐标
之所以要减1,你自己模拟一下
已经明白了,谢谢,新年快乐!
新快!
在处理前缀和的双重循环的结束条件中,为什么不可以是 i<=maxx 和 j<=maxy ?最大的一项不应该就是 sum[maxx][maxy] 吗?超出这个范围之后的各项都是0,相当于没加,也就没有意义了不是吗?但是我把处理前缀和的双重循环的条件换成上述条件之后就会WA是为啥啊?
你把数组大小改大一点,改到原来的两倍应该就可以了
hhhhh
不要水了
《直接暴力枚举》那你怎么不暴力枚举最小圆覆盖……能不能再详细点
我看得懂就行了hh
我看不懂就不行了hh
az
我以后写请注意些hh
hhh
hhhh