CSP 202104-2 前缀和

3 邻域均值

题意:

在这里插入图片描述
现给定邻域参数 r 和阈值 t , 试统计输入灰度图像中有多少像素处于较暗区域。
在这里插入图片描述

Round 1

首先注意到:
在这里插入图片描述
根据数据范围可以知道,暴力肯定只能通过部分样例,必须先对输入数据进行预处理。这里想到的是用二维前缀和去做,通过先预处理出所有矩形框之和,之后的查询可以直接获取相应矩形框中的sum。

# Input
4 16 1 6
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
# Output √
7

# Input
11 8 2 2
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 7 0 0 0 7 0 0 7 7 0
7 0 7 0 7 0 7 0 7 0 7
7 0 0 0 7 0 0 0 7 0 7
7 0 0 0 0 7 0 0 7 7 0
7 0 0 0 0 0 7 0 7 0 0
7 0 7 0 7 0 7 0 7 0 0
0 7 0 0 0 7 0 0 7 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
# Output   (should be 83)
40

迅速找到原因,这里输出的时候没有注意到题干中所说的是average<=t。

还有一个致命错误:这里要考虑边界,区域框是否已经超出了图像大小,以及就算要这样写也应该是 -sum[i-r][j+r]-sum[i+r][j-r]

果然,题许久不写脑子容易生锈2333,一切都从头开始了…
在这里插入图片描述

Round 2

关于边界情况
在这里插入图片描述

需要特别注意的是 sum[l_row-1][r_col]-sum[r_row][l_col-1] 里的 -1
在这里插入图片描述
在这里插入图片描述
另外 CSP的头文件卡得特别严格,如果使用 memset() 一定要加 <cstring> 头文件,不然会一直 编译错误

特别注意:是可以使用万能头 <bits/stdc++.h> 的。

完整代码

//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=605;
int a[maxn][maxn],sum[maxn][maxn];
int main()
{
    
    
    int n,l,r,t,cnt;
    cin>>n>>l>>r>>t;
    cnt=0;
    memset(a,0,sizeof(a));
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++)
    {
    
    
        for(int j=1;j<=n;j++)
        {
    
    
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
    
    
        for(int j=1;j<=n;j++)
        {
    
    
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];//这句也可以直接并到上面
        }
    }
    // for(int i=1;i<=n;i++)
    // {
    
       
    //     for(int j=1;j<=n;j++)
    //         printf("%d ",sum[i][j]);
    //     printf("\n");
    // }
    for(int i=1;i<=n;i++)
    {
    
    
        for(int j=1;j<=n;j++)
        {
    
    
            int ans,num;
            int l_row,r_row,l_col,r_col;
            l_row=max(i-r,1);
            r_row=min(i+r,n);
            l_col=max(j-r,1);
            r_col=min(j+r,n);
            ans=sum[r_row][r_col]-sum[l_row-1][r_col]-sum[r_row][l_col-1]+sum[l_row-1][l_col-1];
            num=(r_row-l_row+1)*(r_col-l_col+1);
            if(ans<=t*num) // 注意这个地方应该是平均值<=t,而不是sum,还需要去统计此时区域中的元素个数
                cnt++;
        }
    }
    //printf("%d\n",cnt);
    cout<<cnt<<endl;
    return 0;
}

总结

思路很简单,看到题目基本上就知道怎么写,但是容易忽略细节。也是因为许久没写题了,手感有点欠,上来就写bug了。不过还好,很快就能发现问题所在。总而言之,以后一定要坚持写题,保持手感。CSP 200分应该是很容易能拿到了,毕业要求也不高,但是冲奖学金的400分的话,还要多点时间准备准备,毕竟退役后的寄几已经快一年半没怎么写题了…

猜你喜欢

转载自blog.csdn.net/Nismilesucc/article/details/119922253
CSP