题目来源
解题思路
题目求解过程中,需要遍历每一个数据 A[i][j] (0< i, j <=n) 来获取它的领域均值。
暴力解法
遍历每个数据时都需要单独算一次它的领域均值,那么算法时间复杂度为O(n * n * r)
非暴力解法
步骤一)
设置一个 areaSum[i][j] (0<=i, j<=n) 来记录A[r][c]数组中,0<r<=i 以及0< c <= j 元素之和。
(在i = 0 或者 y = 0时, areaSum[i][j] = 0,这样在计算areaSum时就不用判断 i-1/ j-1会不会小于0)。
int areaSum[601][601] = {0};
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
int tmp;
cin>>tmp;
areaSum[i][j] = -areaSum[i - 1][j - 1] + areaSum[i - 1][j] + areaSum[i][j - 1] + tmp;
}
}
步骤二)
在遍历每个数据时可以借助 areaSum 来辅助计算领域均值, 这样能将时间复杂度降为 O(n * n)。
如下图所示,当前数据(红色块)的领域(红色区块) = 黄色区块 - 黑色区块 + 绿色区块 + 蓝色区块。
根据上图可以看出来,在遍历每个数据计算其邻域时,还需要记录紫色块下标(u, r), 以及黄色块下标(d, l)才能求出黑色区块数据大小 areaSum[d][l]、绿色区块中数据大小areaSum[d][r]、蓝色区块中数据大小areaSum[u][l]、黄色区块中数据大小areaSum[u][r]。
int d = max(0, i - R - 1), u = min(n, i + R);
int l = max(0, j - R - 1), r = min(n, j + R); // 不要将 R 与 r 混淆了。
double cur = (double)(areaSum[u][r] - areaSum[u][l] - areaSum[d][r] + areaSum[d][l]) / ((u - d) * (r - l) ) ;
完整代码
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int n, L, R, T;
cin>>n>>L>>R>>T;
int areaSum[601][601] = {0};
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
int tmp;
cin>>tmp;
areaSum[i][j] = -areaSum[i - 1][j - 1] + areaSum[i - 1][j] + areaSum[i][j - 1] + tmp;
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
int d = max(0, i - R - 1), u = min(n, i + R);
int l = max(0, j - R - 1), r = min(n, j + R); // 不要将 R 与 r 混淆了。
double cur = (double)(areaSum[u][r] - areaSum[u][l] - areaSum[d][r] + areaSum[d][l]) / ((u - d) * (r - l) ) ;
if (T >= cur) {
++ans;
}
}
}
cout<<ans<<endl;
return 0;
}