CCF202104-2 邻域均值详解《越努力,越幸运》

/*
 * @Author: 365JHWZGo
 * @Description: 邻域均值
 * @Date: 2021-08-29 17:50:17
 * @FilePath: \VScodeC++practice\ccf\linyujunzhi1.cpp
 * @LastEditTime: 2021-08-29 20:30:04
 * @LastEditors: 365JHWZGo
 */
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
    std::ios::sync_with_stdio(false);
    int n, L, r, t, ans = 0, temp = 0;
    double times = 0.0;		//!!!!!times是double类型,否则后面/后为整数
    cin >> n >> L >> r >> t;
    int A[n][n] = {0};
    int pro[n][n];
   // double pp[n][n] = {0.0}; //辅助函数

	//初始化
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> A[i][j];
            pro[i][j] = 0;
        }
    }

	//赋值
    for (int i = 0; i < n; i++)	//控制行
    {
        for (int j = 0; j < n; j++)//控制列
        {
            if (j - 1 == -1)	//初始化计算每行第一列,pro[]来源
            {
                int ti, tj;
                ti = i - r;
                tj = j - r;
                if (ti < 0)	//当构不成全图时,从0开始
                    ti = 0;
                if (tj < 0)//当构不成全图时,从0开始
                    tj = 0;
                for (int x = ti; x >= 0 && x - i <= r && x < n; x++)
                {
                    for (int y = tj; y >= 0 && y - j <= r && y < n; y++)
                    {
                        if (A[x][y] == 0)
                        {
                            times += 1.0;
                            continue;
                        }
                        temp += A[x][y];
                        times += 1.0;
                    }
                }
                pro[i][j] = temp;
            }
            else	//其他情况
            {

                double ft = 0.0, ht = 0.0;	//ft重叠部分前的计算的次数,ht重叠部分后计算的次数
                int before = 0, behind = 0;	//before重叠部分前的值,behind重叠部分后的值
                //before
                for (int k = i - r; j - r - 1 >= 0 && k <= i + r; k++)
                {
                    if (k >= 0&&k<n)	//很重要!!!!表明只在A矩阵以内的值才计算
                    {
                        before += A[k][j - r - 1];

                        ft += 1.0;
                    }
                }
                //behind
                for (int k = i - r; j + r < n && k <= i + r; k++)
                {

                    if (k >= 0&&k<n)
                    {
                        behind += A[k][j + r];
                        ht += 1.0;
                    }
                }
                temp = temp + pro[i][j - 1] - before + behind;	//紫色=橙色-绿色+粉色
                times = times - ft + ht;
                pro[i][j] = temp;
            }

            if (temp / times <= t)
            {
                ans += 1;
                //pp[i][j] = temp / times;
            }
            temp = 0;
        }
        times = 0.0;
    }
    cout << ans;

    return 0;
}

核心思路:
在这里插入图片描述
如图所示:在矩阵A数组中,橙色框住的是A(0)(2)所需计算的值的范围,而紫色圈住的是A(0)(3),其中间有重复值,为了节省计算量,将前者的计算量存储在pro[]数组中,所以在计算紫色数组和时只需要将绿色的部分剪掉,再加上粉色的部分。

紫色=橙色-绿色+粉色;

这个公式适用于所有值
(除第一列以外,因为该公式依赖于同一行的前一个pro数组中的内容,因此需要单独计算第一列)

在这里插入图片描述
与君共努力!

改进了一下

#include <iostream>
using namespace std;
int main()
{
    std::ios::sync_with_stdio(false);
    int n, L, r, t, ans = 0, temp = 0;
    double times = 0.0;
    cin >> n >> L >> r >> t;
    int A[n][n] = {0};
    int pro[n][n];
    double pp[n][n] = {0.0};
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> A[i][j];
            pro[i][j] = 0;
        }
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int ti, tj;
            ti = i - r;
            tj = j - r;
            if (ti < 0)
                ti = 0;
            if (tj < 0)
                tj = 0;
            if (j == 0)
            {
                for (int x = ti; x >= 0 && x - i <= r && x < n; x++)
                {
                    for (int y = tj; y >= 0 && y - j <= r && y < n; y++)
                    {
                        temp += A[x][y];
                        times += 1.0;
                    }
                }
            }
            else
            {
                double ft = 0.0, ht = 0.0;
                int before = 0, behind = 0;
                for (int k = ti; k < n && k <= i + r; k++)
                {
                    if (j - r - 1 >= 0)
                    {
                        before += A[k][j - r - 1];
                        ft += 1.0;
                    }
                    if (j + r < n)
                    {
                        behind += A[k][j + r];
                        ht += 1.0;
                    }
                }
                temp = temp + pro[i][j - 1] - before + behind;
                times = times - ft + ht;
            }
            pro[i][j] = temp;
            if (temp / times <= t)
            {
                ans += 1;
                pp[i][j] = temp / times;
            }
            temp = 0;
        }
        times = 0.0;
    }
    cout << ans;
    return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

365JHWZGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值