CSP CCF: 202104-2 邻域均值 (C++)

题目来源

CSP 202104-2 邻域均值

解题思路

题目求解过程中,需要遍历每一个数据 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)

如下图所示,当前数据(红色块)的领域(红色区块) = 黄色区块 - 黑色区块 + 绿色区块 + 蓝色区块
A[i][j]的邻域计算示意图
根据上图可以看出来,在遍历每个数据计算其邻域时,还需要记录紫色块下标(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;
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值