Python-CCF:20190903 字符画

题目

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

用时

这个看题就头大了,所以也没计时,边写博客边看的
花了小20分钟看题目描述
然后才发现里面基本都是没用的
换句话说
题目描述对不对?对。
它对解题有没有帮助?没有。
出题人脑子有泡
幸亏九月份没考
不然我心态就炸了
还有
考试的机子是Win的我拿头去写Linux命令?
在这里插入图片描述真是服了

思路分析

  1. 24位图:每个像素由24b即3B来表示,如 #ABCDEF
    该像素的RGB分量分别为0xAB 0xCD 0xEF

  2. 然后看输入格式
    在这里插入图片描述
    2 2 (原图片宽2像素,高2像素)
    1 2 (分成宽1像素,高2像素的块)
    #111111
    #0
    #000000
    #111
    (原图的四个像素,从左到右,从上到下,注意缩写的问题)

  3. 输出格式
    在这里插入图片描述

ASCII码对照表

十六进制值 解释
1B ESC
5B [
34 4
38 8
3B ;
32 2
6D m
20 空格
30 0
0A 换行

ESC用\033表示,翻译成Linux终端能识别的命令就是

\033[48;2;8;8;8m  \033[0m\n

即将字符背景色设为RGB =(8, 8, 8)的色号,字符颜色默认,输出字符为两个空格
在这里插入图片描述执行一下试试

在这里插入图片描述 换一个背景色为(255, 255, 255)看看
在这里插入图片描述这些就是那个脑残问题描述里说的内容,做题时只需要输出那堆ASCII码序列就行了

还有很重要的一点:因为输出的字符是空格所以前景色是不需要设置的,也就是说输出序列中绝对不会出现对前景色的更改语句!只改背景色就可以了
在这里插入图片描述出题人就是个傻叉,故意混淆视听

  1. 样例解释
    分成两个块后,每个块都包含上下两个像素,块的RGB值取两个像素的均值(向下取整)
    比如第一像素#111111和第三像素#000000属于同一块
    十进制的RGB分别为(17, 17, 17)和(0, 0, 0)
    取均值后块的RGB值为十进制的(8, 8, 8)
    第二像素#0和第四像素#111属于同一块
    取均值后块的RGB值也为十进制的(8, 8, 8)
    输出时按行和块输出,每个空格代表一个块,每输出完一行输出一个换行符
    总块数为(2*2)/(1*2)=2
    行数为2/2=1

代码

80分,主要是运行超时了
输出都没问题
应该是那个三重循环时间复杂度太高了
正在想办法重构
我太难了…
在这里插入图片描述

class Pixel:
    # 像素类

    R = 0
    G = 0
    B = 0
    # 十进制RGB值

    def set_RGB(self, R, G, B):
        self.R = R
        self.G = G
        self.B = B


def str_to_ASCII(mystr):
    # 将字符串逐个字符转为\xAB的形式
    final_ASCII_str = ''
    for mychr in mystr:
        final_ASCII_str += hex(ord(mychr)).replace('0x', '\\x')
    return final_ASCII_str


def background_color(R, G, B):
    # 传入十进制的RGB值生成更改背景色的ASCII序列
    background_color_sequence = '\\x1b' + str_to_ASCII('[48;2')
    background_color_sequence += str_to_ASCII(';' + str(R) + ';' + str(G) + ';' + str(B) + 'm')

    return background_color_sequence


if __name__ == "__main__":
    img_width, img_height = map(int, input().split(' '))
    # 获得图片的宽度、高度

    block_width, block_height = map(int, input().split(' '))
    # 获得块的宽度、高度

    rows_num = int(img_height / block_height)
    # 行数
    row_blocks_num = int(img_width / block_width)
    # 每行块数

    img_pix = []
    # 图片像素存储,如两行四列图片的格式为
    '''
    [
        [pixel, pixel, pixel, pixel],
        [pixel, pixel, pixel, pixel]
    ]
    '''

    block_pix_group = [[[] for rbn in range(row_blocks_num)]for rn in range(rows_num)]
    # 一个块包含数个pixel对象
    block_pix = []
    # 取均值后每块只按一个pixel对象存储

    lower_sequence = ''

    reset_sequence = '\\x1b' + str_to_ASCII('[0m')
    # 重置序列 \x1b\x5b\x30\x6d\x0a 即 ESC[0m

    terminal_color = [0, 0, 0]
    # 初始终端颜色

    for ih in range(img_height):
        img_pix.append([])
        for iw in range(img_width):
            # 读入每个像素并存储为十进制RGB分量
            img_pix[ih].append(Pixel())

            orig_HEX_RGB = input().replace('#', '')
            # 拿到一个十六进制RGB值如ABCDEF

            if len(orig_HEX_RGB) == 1:
                # 缩写为1的情况
                orig_HEX_RGB += orig_HEX_RGB * 5

            elif len(orig_HEX_RGB) == 3:
                # 缩写为3的情况
                orig_HEX_RGB = orig_HEX_RGB[0] * 2 + orig_HEX_RGB[1] * 2 + orig_HEX_RGB[2] * 2

            img_DEC_R = int(orig_HEX_RGB[0:2], 16)
            img_DEC_G = int(orig_HEX_RGB[2:4], 16)
            img_DEC_B = int(orig_HEX_RGB[4:6], 16)
            # 获得图片每个像素的十进制RGB值

            img_pix[ih][iw].set_RGB(img_DEC_R, img_DEC_G, img_DEC_B)
            # 存储到pixel对象中
            block_pix_group[ih // block_height][iw // block_width].append(img_pix[ih][iw])
            # 确定每个块包含图片中的哪几个pixel对象

    for rn in range(rows_num):
        block_pix.append([])
        for rbn in range(row_blocks_num):
            block_pix[rn].append(Pixel())

            block_sum_R = 0
            block_sum_G = 0
            block_sum_B = 0

            # TODO:分离下面的三重循环
            for po in block_pix_group[rn][rbn]:
                # 分别求每个块包含所有pixel对象的R、G、B的和
                block_sum_R += po.R
                block_sum_G += po.G
                block_sum_B += po.B

            block_average_R = block_sum_R // (block_width * block_height)
            block_average_G = block_sum_G // (block_width * block_height)
            block_average_B = block_sum_B // (block_width * block_height)
            # 向下取整求每块的RGB均值

            block_pix[rn][rbn].set_RGB(block_average_R, block_average_G, block_average_B)
            # 存放到一个pixel对象中

            this_block_pix_R = block_pix[rn][rbn].R
            this_block_pix_G = block_pix[rn][rbn].G
            this_block_pix_B = block_pix[rn][rbn].B
            # 一个块的RGB值

            if [this_block_pix_R, this_block_pix_G, this_block_pix_B] != terminal_color:
                # 如果块与终端颜色不同
                if this_block_pix_R == 0 and this_block_pix_G == 0 and this_block_pix_B == 0:
                    # 如果与默认色相同
                    lower_sequence += reset_sequence
                    # 则加一个重置序列
                else:
                    lower_sequence += background_color(this_block_pix_R, this_block_pix_G, this_block_pix_B)
                    # 与默认色不同则加一个更改背景色的序列

                terminal_color = [this_block_pix_R, this_block_pix_G, this_block_pix_B]
                # 更新终端背景色

            lower_sequence += str_to_ASCII(' ')
            # 无论块RGB与终端是否相同都要输出一个空格

        if terminal_color != [0, 0, 0]:
            # 输出一行后如果终端颜色不是默认的000则加一个重置序列
            lower_sequence += reset_sequence
            terminal_color = [0, 0, 0]
            # 重置终端背景色
        lower_sequence += '\\x0a'
        # 每输出一行必加一个换行

    # 所有块全部处理完一遍

    upper_sequence = ''
    for i in range(len(lower_sequence)):
        if lower_sequence[i] in {'a', 'b', 'c', 'd', 'e', 'f'}:
            # 如果是小写字母abcdef
            upper_sequence += lower_sequence[i].upper()
            # 转为大写
        else:
            upper_sequence += lower_sequence[i]
    print(upper_sequence)



测试用例

引用自此博客,C满分代码
一定要注意最终输出的格式!
第一:是ASCII码格式的 \x..
第二:输出的ABCDEF都是大写的,如果输出小写则0分
第三:输出只有一行,不要加换行

1 1
1 1
#010203
\x1B\x5B\x34\x38\x3B\x32\x3B\x31\x3B\x32\x3B\x33\x6D\x20\x1B\x5B\x30\x6D\x0A

2 2
1 2
#111111
#0
#000000
#111
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x20\x1B\x5B\x30\x6D\x0A

1 1
1 1
#0
\x20\x0A

2 2
2 1
#111111
#0
#000000
#111
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A

2 2
2 1
#111111
#0
#000000
#000
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A\x20\x0A

3 2
1 2
#0
#0
#010101
#010102
#0
#0
\x1B\x5B\x34\x38\x3B\x32\x3B\x30\x3B\x30\x3B\x31\x6D\x20\x1B\x5B\x30\x6D\x20\x20\x0A

1 2
1 2
#123456
#abcdef
\x1B\x5B\x34\x38\x3B\x32\x3B\x39\x34\x3B\x31\x32\x38\x3B\x31\x36\x32\x6D\x20\x1B\x5B\x30\x6D\x0A

2 1
2 1
#654321
#fedcba
\x1B\x5B\x34\x38\x3B\x32\x3B\x31\x37\x37\x3B\x31\x34\x33\x3B\x31\x30\x39\x6D\x20\x1B\x5B\x30\x6D\x0A

总结

说难也没有很难吧
可能是我数据结构选的不好
导致必须用三重循环才能拿到需要的数据
翻遍全网也没找到一份Python的满分代码
只看到一个和我一样运行超时的80分
有点难受
不过还是感谢Python提供了许多内置函数如replace ord hex int等等等等
我永远喜欢Python

发布了61 篇原创文章 · 获赞 11 · 访问量 4869

猜你喜欢

转载自blog.csdn.net/weixin_43249758/article/details/103985744