Python编程基础题(19-万绿丛中一点红)

Description
对于计算机而言,颜色不过是像素点对应的一个 24 位的数值。现给定一幅分辨率为 M×N 的画,要求你找出万绿丛中的一点红,即有独一无二颜色的那个像素点,并且该点的颜色与其周围所有相邻像素的颜色差充分大。

Input
输入第一行给出三个正整数,分别是 M 和 N(≤ 1000),即图像的分辨率;以及 TOL,是所求像素点与相邻点的颜色差阈值,色差超过 TOL 的点才被考虑。随后 N 行,每行给出 M 个像素的颜色值,范围在 [0,2 ​24 ​​ ) 内。所有同行数字间用空格或 TAB 分开。

Output
在一行中按照 (x, y): color 的格式输出所求像素点的位置以及颜色值,其中位置 x 和 y 分别是该像素在图像矩阵中的列、行编号(从 1 开始编号)。如果这样的点不唯一,则输出 Not Unique;如果这样的点不存在,则输出 Not Exist。
在这里插入图片描述

在这里插入图片描述
参考程序

#满分程序
M,N,TOL=map(int,input().split())
graph=[]
ans=[]
color_dict={}
def Judge(i,j,M,N):
    if i>=0 and i<=N-1 and j>=0 and j<=M-1:
        return True
    else:
        return False

for i in range(N):
    tmp=list(map(int,input().split()))
    for j in tmp:
        try:
            color_dict[j]+=1
        except:
            color_dict[j]=1
    graph.append(tmp)
for i in range(N):
    for j in range(M):
        if color_dict[graph[i][j]]!=1:
            continue
        #下面测试(i,j)的8个邻居
        if Judge(i-1,j-1,M,N):#邻居点是合法的
            if abs(graph[i][j]-graph[i-1][j-1])<=TOL:#色差不满足条件
                continue
        else:
            pass#不合法则不考虑该邻居,换一个邻居
        if Judge(i-1,j,M,N):
            if abs(graph[i][j]-graph[i-1][j])<=TOL:
                continue
        else:
            pass
        if Judge(i-1,j+1,M,N):
            if abs(graph[i][j]-graph[i-1][j+1])<=TOL:
                continue
        else:
            pass
        if Judge(i,j-1,M,N):
            if abs(graph[i][j]-graph[i][j-1])<=TOL:
                continue
        else:
            pass
        if Judge(i,j+1,M,N):
            if abs(graph[i][j]-graph[i][j+1])<=TOL:
                continue
        else:
            pass
        if Judge(i+1,j-1,M,N):
            if abs(graph[i][j]-graph[i+1][j-1])<=TOL:
                continue
        else:
            pass
        if Judge(i+1,j,M,N):
            if abs(graph[i][j]-graph[i+1][j])<=TOL:
                continue
        else:
            pass
        if Judge(i+1,j+1,M,N):
            if abs(graph[i][j]-graph[i+1][j+1])<=TOL:
                continue
        else:
            pass
        ans.append([j+1,i+1,graph[i][j]])

if len(ans)==0:
    print("Not Exist")
elif len(ans)==1:
    print("({0}, {1}): {2}".format(ans[0][0],ans[0][1],ans[0][2]))
else:
    print("Not Unique")

分析:
本题为PAT (Basic Level)1068题。从本题的编程技术或算法设计角度来说,并不难,只是通过全部测试样例,需要格外注意审题,理解题目和给出的测试样例。我结合CSDN上其他大佬的解题经验以及个人体会,总结出以下几点需要注意的地方:
①纠正原题的描述:“该点的颜色与其周围 8 个相邻像素的颜色差充分大”,应改为“该点的颜色与其周围所有相邻像素的颜色差充分大”,应考虑最外围的数据。也有可能是目标点;
②充分理解“独一无二”:这个含义是指,可能存在某个点,它的所有邻居点的像素都满足这个“色差”要求,但是这个点的像素(颜色)在整个矩阵中出现不止一次,那么它就不是独一无二的,因此这样的点不是目标点;
③如何判断是否独一无二:创建字典,在输入数据的同时对每个颜色值统计次数,字典的键:值关系是,颜色值:出现的次数,这样检索较快,也不占用太大空间。
在这里还有一个技巧,就是更新字典时,善用异常处理机制也能给提高效率!判断颜色是否存在于字典中的键时,可以不用in关键字判断,直接交给键查找异常KeyError来处理!(无异常说明键存在,则更新值,有异常则创建键)
如果将输入的颜色平铺成一位数组(N×M个数据),使用count方法会超时!原因是,对于每个点的遍历是O(N×M),然而在这个N×M个数据的一位数组上利用count方法计数,则内层相当于又嵌套了O(N×M),所以时间性能十分低下。
如果采用“以空间换时间”的策略,开2^24的列表存储颜色值的出现次数,虽然时间复杂度降低了,但是这样会内存超限。
综上所述,字典在两者之间作出了平衡。
④充分理解“色差”:差值要加上绝对值再和TOL作比较。

这道题我肝了好久,从代码逻辑到性能优化,提交了不下二三十遍,在这个过程中非常感谢CSDN上其他大佬的经验分享。这段时间刷了好多PAT乙级题,我不由得感叹PAT题还真的不能小觑,都很精品!一道编程题其实也考查了好多知识点,需要选择合适的程序结构、数据结构,同时也要在时间复杂度和空间复杂度之间做出很好的权衡。欢迎各位大佬批评指正,不吝赐教~
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值