ccf 202104-2 邻域均值 python

问题限制

试题编号202104-2
试题名称邻域均值
时间限制1.0s
内存限制512.0MB

试题背景
顿顿在学习了数字图像处理后,想要对手上的一副灰度图像进行降噪处理。不过该图像仅在较暗区域有很多噪点,如果贸然对全图进行降噪,会在抹去噪点的同时也模糊了原有图像。因此顿顿打算先使用邻域均值来判断一个像素是否处于较暗区域,然后仅对处于较暗区域的像素进行降噪处理。

问题描述
在这里插入图片描述
简而言之,就是判断矩阵中每个点的灰度值是否低于邻域均值,关键在于邻域均值的求法
输入格式
在这里插入图片描述
输出格式
输出一个整数,表示输入灰度图像中处于较暗区域的像素总数。
样例1
在这里插入图片描述
样例2
在这里插入图片描述
评价用例规模与约定
在这里插入图片描述
解题思路
30分:bfs思路
起初,鼠鼠把邻域理解成一个圆了,就想着这不妥妥的宽搜吗,于是百般尝试,答案总是对不上,后来仔细读题发现,这个邻域原来是个矩形,于是修改了判定条件,但是由于没有考虑到bfs的时间复杂度,只得了30分,那我就来分析一下bfs的时间复杂度,首先双重循环是一定的,这就n方了,然后由于题目是用邻接矩阵存储数据的,我们需要考虑比较极限的情况,就是半径r刚好等于n-1,那么使用Queue队列模拟bfs就会每次有n*n个元素入队列,所以bfs的时间复杂度就会高达n方,外边的n方和里边的n方一乘就是n的四次方,即使n的范围只到360,但是360的4次方也会超时,所以最起码用队列模拟bfs是不行的,果然最后只得了30分就gg了。

100分:二维前缀和
使用bfs解题其实是把这个问题想复杂了,如果邻域不是圆形,而是一个矩形,完全没必要用bfs,直接二维前缀和就行了,可以把内部O(n^2)时间复杂度直接降到O(1),这样一定可以过,遍历每个点的时候只需要判断要求的矩阵大小即可,即找准x1,y1,x2,y2。

代码实现

#bfs 30分(悲)
from queue import Queue
n,L,r,t=map(int,input().split())
board=[]
for i in range(n):
    board.append(list(map(int,input().split())))
#四个方向
directions={(0,1),(0,-1),(1,0),(-1,0)}
que=Queue()
ans=0
for i in range(n):
    for j in range(n):
    	#先把初始结点入队列
        que.put((i,j))
        #这个地方一定要每次都初始化,因为我们在计算和以及点的数量时,不能因为上一次遍历过了就不计算了
        flag=[[False for p in range(n)] for q in range(n)]
        num=1
        tal=board[i][j]
        while not que.empty():
            point=que.get()
            x=point[0]
            y=point[1]
            #千万记得要修改原始状态,要不就死循环了,这是队列模拟bfs很关键的一个点
            flag[x][y]=True
            for direction in directions:
                new_x=x+direction[0]
                new_y=y+direction[1]
                if n>new_x>=0 and n>new_y>=0 and abs(new_x-i)<=r and abs(new_y-j)<=r and flag[new_x][new_y]==False:
                    que.put((new_x,new_y))
                    num+=1
                    tal+=board[new_x][new_y]
                    flag[new_x][new_y]=True
        if tal<=num*t:
            ans+=1
print(ans)
"""
#队列模拟bfs的模板
directions={四个方向}
que=Queue()
#放进去起点
que.put((i,j))
while not que.empty():
	point=que.get()
	x=point[0]
	y=point[1]
	修改[x][y]点的状态
	for direction in directions:
		new_x=x+direction[0]
		new_y=y+direction[1]
		if n>new_x>=0 and n>new_y>=0 and 状态 and 其他条件:
			que.put((new_x,new_y))
			修改[new_x][new_y]点的状态
"""
#二维前缀和 100分
n,L,r,t=map(int,input().split())
#因为前缀和涉及到i-1,j-1,所以前缀和数组和原数组最好下标从1开始
board=[[0 for i in range(n+1)]]
for i in range(n):
    board.append([0]+list(map(int,input().split())))
ans=0
s=[[0 for i in range(n+1)]for i in range(n+1)]
for i in range(1,n+1):
    for j in range(1,n+1):
        s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+board[i][j]
for i in range(1,n+1):
    for j in range(1,n+1):
    	#这就没什么好说的了,别超过范围
        x1=1 if i-r<=0 else i-r
        y1=1 if j-r<=0 else j-r
        x2=n if i+r>=n else i+r
        y2=n if j+r>=n else j+r
        num=(x2-x1+1)*(y2-y1+1)
        tal=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]
        if tal<=num*t:
            ans+=1
print(ans)

原题链接
链接: ccfcsp认证

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

so.far_away

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

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

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

打赏作者

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

抵扣说明:

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

余额充值