原题:
数据量小得出奇,直接四重循环暴力就能过。
这道题的重点其实不是暴力,而是边界。注意到无线网络发射器能放到边缘处,但那样覆盖到地图的范围就不是一个正方形了。。
曾经想过预处理一下每个子矩阵的公共场所的总数量,然后在这个预处理的答案中再找最大值和有最大值的个数。但我后来发现完全不必要,而且不好写。
边界的处理。C++不能像pascal那样让数组下标变为负,所以我使用了“地图平移”操作。注意到数据范围1≤d≤20,即覆盖范围的边长的一半最大到20,那么,在读入的时候把所有坐标都+20,遍历时的坐标也同样的+20,地图边长最大128,那么遍历的长度就基本确定了:20~148.
刚才说到四重循环,前两重循环枚举放置点,后两重循环以这个枚举点为中心直接计算和,然后维护最大值就好。
如果你不喜欢这么做,可以按照我刚才的做法, 预处理处一个数组,这样可以只循环两层。
AC代码:
1 #include2 #include 3 #include 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