1015 德才论python3无超时

首先说明用改进后的代码并不能保证每次都没有超时,成功的概率在50%左右

本文思路来自于1015 德才论 (25分) Python3 无超时优化过程

一、最初代码

#!/usr/bin/env python
# -*-coding:utf-8 -*-
'''
@File    :   1015.py
@Time    :   2020/03/23 12:50:12
@Author  :   Schiller Xu
@Version :   1.0
@Contact :   schillerxu@qq.com
@License :   (C)Copyright 2020-2021, SchillerXu
@Desc    :   None
'''

data = input().split()
n = int(data[0])
l = int(data[1])
h = int(data[2])

grades = [input().split() for i in range(n)]

result1 = []
result2 = []
result3 = []
result4 = []

grades.sort(key=lambda x: int(x[0]))
grades.sort(key=lambda x: int(x[1]), reverse=True)
grades.sort(key=lambda x: int(x[1])+int(x[2]), reverse=True)

for grade in grades:
    d = int(grade[1])
    c = int(grade[2])
    if d >= l and c >= l:
        if d >= h and c >= h:
            result1.append(grade)
        elif d >= h > c:
            result2.append(grade)
        elif c <= d < h:
            result3.append(grade)
        else:
            result4.append(grade)


m = len(result1)+len(result2)+len(result3)+len(result4)
print(m)
for i in result1+result2+result3+result4:
    print(i[0]+' '+i[1]+' '+i[2])

代码最后有3个超时

二、改进思路

改进思路如下:

  1. 将input改为sys.stdin.readline,把print改成 sys.stdout.write,在数据量比较大的情况下使用sys.stdin.readline会节省时间;
  2. 提前生成分数[0-100]字符到整型映射的字典,score_dict = dict(zip([str(i) for i in range(101)], range(101))),获取德分和才分的时候不再使用int,使用字典映射。为了节省时间,可以把score_dict全部列出来;
  3. 改变数据存储结构,使用三维列表保存数据,索引是德分和才分的总分,范围应该是[2* l l l, 200], l l l是录取的最低分,list[i]默认为0,表示没有总分为2* l l l+ i i i的数据;如果总分相同,那就按照德分排序,所以第二层索引是德分,范围是[ l l l, 100], l i s t [ i ] [ j ] list[i][j] list[i][j]默认为0,表示没有德分为 l + j l+j l+j的数据;如果德分也相同,那就按照准考证号排序,最里面那一层保存的是考生的准考证号。

按照oj平台提供的测试数据,那么才德兼备,列表中的数值应该如下(过滤掉总分不存在的):

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ['10000004'], 0, 0, 0, 0, ['10000011', '10000003'], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ['10000012'], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ['10000013'], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

其中:

10000011 85 80
10000003 85 80
10000004 80 85

三者的总分相同,所以保存在同一个列表里面;10000004的德分是80,那么对应的数据应该在列表下标21的地方;10000003和10000011不仅总分相同,德分也相同,数据被保存在了最里面的列表里面。(三维列表)

这么做的最大好处是不用对总分和德分排序,直接过滤掉值为0的数据就好。

三、最终的代码

#!/usr/bin/env python
# -*-coding:utf-8 -*-
'''
@File    :   1015-1.py
@Time    :   2020/07/08 20:57:36
@Author  :   Schiller Xu 
@Version :   1.0
@License :   (C)Copyright 2020-2021, SchillerXu
@Desc    :   None
'''
import sys

def set_list(r,test_id,d,c):
    #t是总分-最底线
    t=d+c-2*l
    ind=d-l
    if r[t]==0:
        r[t]=[0]*(100-l+1)
        r[t][ind]=[test_id]
    elif r[t][ind]==0:   #总分相同,德分不同
        r[t][ind]=[test_id]
    else:                #总分相同,德分也相同
        r[t][ind].append(test_id)

def print_list(r):
    for i in range(200-2*l,-1,-1):
        #总分从大到小,相同的在一个列表里面
        if r[i]:
            for j in range(len(r[i])-1,-1,-1):
                #德分从大到小,相同的在同一个列表里面
                if r[i][j]:
                    #根据准考证号升序排列
                    for t in sorted(r[i][j]):
                        sys.stdout.write(stu.get(t))

n,l,h=map(int,sys.stdin.readline().split())
r1=[0]*(200-2*l+1)
r2=[0]*(200-2*l+1)
r3=[0]*(200-2*l+1)
r4=[0]*(200-2*l+1)

stu=dict()

score_dict = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
              '10': 10, '11': 11, '12': 12, '13': 13, '14': 14, '15': 15, '16': 16, '17': 17,
              '18': 18, '19': 19, '20': 20, '21': 21, '22': 22, '23': 23, '24': 24, '25': 25,
              '26': 26, '27': 27, '28': 28, '29': 29, '30': 30, '31': 31, '32': 32, '33': 33,
              '34': 34, '35': 35, '36': 36, '37': 37, '38': 38, '39': 39, '40': 40, '41': 41,
              '42': 42, '43': 43, '44': 44, '45': 45, '46': 46, '47': 47, '48': 48, '49': 49,
              '50': 50, '51': 51, '52': 52, '53': 53, '54': 54, '55': 55, '56': 56, '57': 57,
              '58': 58, '59': 59, '60': 60, '61': 61, '62': 62, '63': 63, '64': 64, '65': 65,
              '66': 66, '67': 67, '68': 68, '69': 69, '70': 70, '71': 71, '72': 72, '73': 73,
              '74': 74, '75': 75, '76': 76, '77': 77, '78': 78, '79': 79, '80': 80, '81': 81,
              '82': 82, '83': 83, '84': 84, '85': 85, '86': 86, '87': 87, '88': 88, '89': 89,
              '90': 90, '91': 91, '92': 92, '93': 93, '94': 94, '95': 95, '96': 96, '97': 97,
              '98': 98, '99': 99, '100': 100}

for _ in range(n):
    input_=sys.stdin.readline()
    test_id,d,c=input_.split()
    d=score_dict[d]
    c=score_dict[c]
    
    if d>=l and c>=l:
        stu[test_id]=input_
        if d>=h and c>=h:
            set_list(r1,test_id,d,c)
        elif d>=h>c:
            set_list(r2,test_id,d,c)
        elif c<=d<h:
            set_list(r3,test_id,d,c)
        else:
            set_list(r4,test_id,d,c)

print(len(stu))
# print(r1)
# for r in r1:
#     if r:
#         print(r)
print_list(r1)
print_list(r2)
print_list(r3)
print_list(r4)

主要改进的地方就是数据存储的结构,三维列表需要好好理解。

四、参考资料

1015 德才论 (25分) Python3 无超时优化过程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值