CCF-CSP认证 202104-2 邻域均值
题意描述
一副图像是由一个灰度值矩阵组成的 定义领域的概念 一个点的邻域就是指以这个点为中心 长为横坐标±r 宽为纵坐标±r 的点组成的矩阵 若这个领域内所有点的灰度值之和取均值 小于等于某个阈值t 就称这个点处于较暗区域 本题就要我们就有多少点位于较暗区域
输入输出格式
输入 n 矩阵规模 L 灰度值上限 r t 阈值
数据规模
n <= 600
算法设计
根据数据规模 感觉 3次方 算法也是可以过的 但是 依次枚举矩阵每个点 再枚举每个点邻域内的点 一定会超时
这里提供了基于一维前缀和优化的方法 复杂度为O(n^3) 原理很简单 先计算前缀和数组 再枚举矩阵中的每个点 再枚举该点邻域的每一行 在常量时间内计算出该行灰度值的和 最后计算完毕后 除以邻域灰度值个数 和 t 比较即可
注意 这里要除的话 一定要做浮点比较 !
c++11代码
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
gg ni, li, ri, ti;
cin >> ni >> li >> ri >> ti;
vector<vector<gg>> v(ni, vector<gg>(ni + 1));
for (auto &i : v){
for (gg j = 1; j <= ni; j++)
{
cin >> i[j];
}
}
for(auto& i : v){
for (gg j = 1; j <= ni;j++){ // 前缀和
i[j] = i[j - 1] + i[j];
}
}
gg tmp = 0;
gg res = 0;
for (gg i = 0; i < ni;i++){
for (gg j = 1; j <= ni;j++){
tmp = 0;
gg leftup = (j - ri < 1 ? 1 : j - ri);
gg rightup = (j + ri > ni ? ni : j + ri);
gg leftdown = (i - ri < 0 ? 0 : i - ri);
gg rightdown = (i + ri > ni - 1 ? ni - 1 : i + ri);
gg num = (rightdown - leftdown + 1) * (rightup - leftup + 1); // 灰度值的个数
while(leftdown <= rightdown){ // 枚举每行
tmp += (v[leftdown][rightup] - v[leftdown][leftup - 1]);
leftdown++;
}
if(tmp * 1.0 / num <= ti) // 要进行浮点比较
res++;
}
}
cout << res;
return 0;
}