无线网络发射选址

原题:https://www.luogu.org/problem/show?pid=2038

数据量小得出奇,直接四重循环暴力就能过。

这道题的重点其实不是暴力,而是边界。注意到无线网络发射器能放到边缘处,但那样覆盖到地图的范围就不是一个正方形了。。

曾经想过预处理一下每个子矩阵的公共场所的总数量,然后在这个预处理的答案中再找最大值和有最大值的个数。但我后来发现完全不必要,而且不好写。

边界的处理。C++不能像pascal那样让数组下标变为负,所以我使用了“地图平移”操作。注意到数据范围1≤d≤20,即覆盖范围的边长的一半最大到20,那么,在读入的时候把所有坐标都+20,遍历时的坐标也同样的+20,地图边长最大128,那么遍历的长度就基本确定了:20~148.

刚才说到四重循环,前两重循环枚举放置点,后两重循环以这个枚举点为中心直接计算和,然后维护最大值就好。

如果你不喜欢这么做,可以按照我刚才的做法, 预处理处一个数组,这样可以只循环两层。

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define maxn 233
 5 using namespace std;
 6 int d,n,x,y,k;
 7 int a[maxn][maxn];
 8 const int edge = 20;
 9 const int maxmap = 128;
10 int maxv;
11 int summat;
12 int cnt = 1;
13 int main(){
14     cin >> d;
15     cin >> n;
16     for (int i=1;i<=n;i++){
17         cin >> x >> y;
18         cin >> a[x+edge][y+edge];
19     }
20     for (int i=edge;i<=edge+maxmap;i++)
21         for (int j=edge;j<=edge+maxmap;j++){
22             for (int p=i-d;p<=i+d;p++)
23                 for (int q=j-d;q<=j+d;q++)
24                     summat+=a[p][q];
25             if (maxv == summat)
26                 cnt++;
27             else if(maxv<summat)
28                 cnt = 1;
29             maxv = max(summat,maxv);
30             summat = 0;
31         }
32     cout << cnt << " " << maxv << endl;
33     return 0;
34 }
原文地址:https://www.cnblogs.com/OIerShawnZhou/p/7457899.html