找回密码
 立即注册
搜索
热搜: 活动 交友
查看: 66|回复: 0

【acsl全明星初级组真题】

[复制链接]

14

主题

39

回帖

1039

积分

专家程序员

积分
1039
发表于 昨天 15:31 | 显示全部楼层 |阅读模式
本帖最后由 脆脆大奶酪 于 8-14-2025 15:31 编辑

问题: 行程长度编码是一种数据压缩技术,适用于存在大量重复值的数据(如黑白图像)。其原理是将多个连续重复的字符替换为该字符后紧跟其重复出现的次数。这种压缩技术是无损的,这意味着可以用压缩版本重建原始数据源。例如,输入字符串 ABBCEEEEAAAAAADDDAAA。其编码过程中的每次计数都用一个 16 进制数表示,并且每次计数都比字符实际连续重复次数少 1。编码后,该字符串将变为 A0B1C0E3A5D2A2。原始的字符串包含 20 个字符,而编码后的字符串则缩减至 14 个字符。如果某个字符连续重复出现的次数超过 16 次,则需要多次输出该字符。例如,一个由 5 个 C 后跟 30 个 B 再跟 2 个 A 组成的字符串将被压缩为C4BFBDA1。 在程序的编码部分,你将接收到一个字母数字字符串,随后你所编写的程序会输出其对应的编码形式。在程序的解码部分,你将接收到一个已经经过行程长度编码处理的字母数字字符串。你需要将其解码并以单个字符串的形式返回。一个字符串用字母 E 引导,表示该字符串需编码;一个字符串用字母 D 引导,表示该字符串需解码。


你所编写的程序还必须支持以下用 EV 或 DV 引导的变体:无需将连续重复出现的字符以 16 个为一组进行划分,直接输出字符连续重复出现的次数即可,次数用16 进制表示。当字符连续重复出现次数表示为 2 位或更多位的16 进制数字时,这个 16 进制数前后要用破折号隔开。在这种变体中,计数结果即字符实际重复出现的次数,无需减 1。例如 ABBCEEEEAAAAAADDDAAA 被编码为 A1B2C1E4A6D3A3 ;由 5 个C ,后接 30 个 B,随后是 2 个 A 组成的字符串可能被压缩为 C5B-1E-A2。  

输入: 两个数据字符串。第一个字符串由 1 或 2 个字符组成,代表编码类型 (E,D,EV,DV) 。第二个字符串是待编码或解码的信息。所有信息都遵循有效的格式规范。在编码后的字符串中,所有的 16 进制数字都将用大写字母表示。除了用作破折号的“-”外,键盘上的所有字符都可以用于构成信息的内容。

输出: 根据输入的代码,输出一个字符串,表示编码或解码后的信息。   

样例:
输入E
      ABBCEEEEAAAAAADDDAAACCCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAA
输出A0B1C0E3A5D2A2C4BFBDA1
输入EV
      ABBCEEEEAAAAAADDDAAACCCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAA
输出A1B2C1E4A6D3A3C5B-1E-A2
输入D
      a0b1a2dAfFfFfEE2
输出abbaaadddddddddddfffffffffffffffffffffffffffffffffffffffffffffffEEE
输入DV
      a1b2a3dBf-2F-E3
输出abbaaadddddddddddfffffffffffffffffffffffffffffffffffffffffffffffEEE






看似是一道题,其实是一组四道题,我们就按照样例的顺序一个一个来写。
首先是E和EV:
把连续相同字符变成一个字符加表示数量的十六进制数,区别在于E模式下最多十六个一组,且数字是实际数量减一,换句话说就是字符后面只跟一位十六进制数,超出十六个的就放进下一组;而EV模式下则没有数量限制,因而也不必减一去追求形式的美观,只需将总数转为十六进制跟在字符后即可,同时为了清晰,每个十六进制数前后要加上一个“-”,以区分字符和十六进制数。
然后就是代码实现:

n = input()
a = input()
xLst = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
nLst = []
if n == 'E':
    w = ''
    cnt = 0
    x = 0
    for i in range(len(a)):
        if x == 0:
            x = a[0]
            continue
        if a == x:
            cnt +=1
        else:
            w += x
            w2 = 'F'+x
            while cnt >=16:
                w +=w2
                cnt-=16
            w+= xLst[cnt]
            cnt = 0
            x = a
    if x != 0:
        w += x
        w2 = 'F'+x
        while cnt >=16:
            w +=w2
            cnt-=16
        w+= xLst[cnt]
    print(w)
elif n == 'EV':
    x = 0
    w = ''
    cnt = 0
    for i in range(len(a)):
        if x == 0:
            x = a[0]
        if a == x:
            cnt +=1
        else:
            w += x
            if cnt <16:
                w+= xLst[cnt]
            else:
                w+='-'
                n2 = hex(cnt)[2:]
                for j in range(len(n2)):
                    if '0' <= n2[j] <= '9':
                        w += n2[j]
                        continue
                    x2 = ord(n2[j])
                    x2 -= 32
                    w += chr(x2)
                w += '-'
            cnt = 1
            x = a
    if x != 0:
        w+= x
        if cnt <16:
            w+= xLst[cnt]
        else:
            w+='-'
            n2 = hex(cnt)[2:]
            for j in range(len(n2)):
                if '0' <= n2[j] <= '9':
                    w += n2[j]
                elif 'a'<=n2[j]<='f':
                    x2 = ord(n2[j])
                    x2 -= 32
                    w += chr(x2)
            w +='-'
    print(w)
具体思路就是先循环整个字符串,记录上一个字符,一样就计数加一,不一样就先把上一个字符和数字写入答案,再把计数归零,在E模式下如果计数超过16则也当作不同字符处理即可(示例程序中采取的是先全部计数再用while循环16个一组进行分离,也可以),EV模式更简单,不需要额外判断,只需要在前后加上一个“-”
最后我们需要的只有进制转换的代码,建议使用hex()函数,hex(n)会返回字符串形式的16进制数,且前两位是十六进制数的标志0x,这里我们人为去掉前两位就好,这样可以快速进行转换
然后是D和DV:
也就是刚刚两问的反向操作,通过输出得到输入,其实反而更加容易因为十六进制数转十进制可以直接使用int()函数,int(str,16)即可把字符串对应的十六进制数转换为十进制数,注意此处不需要加0x的前缀
代码:

elif n == 'D':
    w = ''
    s=0
    for i in range(len(a)):
        if s == 0:
            x = a
            s=1
        else:
            for j in range(xLst.index(a)+1):
                w += x
            s=0
    print(w)
elif n == 'DV':
    w = ''
    s = 0
    cnt = 0
    w2 = ''
    r = 1
    for i in range(len(a)):
        if s == 0:
            x = a
            s = 1
        else:
            if a == '-' and s == 1:
                s = 2
                continue
            if s == 2:
                if a == '-':
                    while w2!='':
                        cnt += r*xLst.index(w2[-1])
                        r *= 16
                        w2 = w2[:-1]
                    for j in range(cnt):
                        w += x
                    s,cnt,r = 0,0,1
                else:
                    w2 += a
            else:
                for j in range(xLst.index(a)):
                    w += x
                s=0
    if(s == 2):
        while w2!='':
            cnt += r*xLst.index(w2[-1])
            r *= 16
            w2 = w2[:-1]
            for j in range(cnt):
                w += x
    elif (s == 1):
        for j in range(xLst.index(a)):
            w += x
    print(w)


这次程序结构和思路较为简单,就没有加注释,同样地,如果有疑问还请留言,其他同学看见也可以共同进步
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RealDevClub ( 沪ICP备2024093864号-1 )

GMT+8, 8-15-2025 22:58 , Processed in 0.065293 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表