CCF-CSP-202012-2-期末预测之最佳阈值-python100分

方法1:
暴力,把每个阈值和m个条目进行判断,计数。只能过70%的用例

方法2:
统计一个阈值预测准确的数量并不需要一个个判断的嘛,小于该阈值的分数,对应结果要是0(挂)才算正确;大于等于该阈值的分数,对应结果要是1(过)才算正确。所以可先用字典统计每个阈值挂了的(0)和过了的(1)数量,然后按分数大小排序(这一步已经去重复了)。计算阈值正确数的时候,从该阈值开始,往低分处走统计0的数量,往高分处走统计1的数量,最后加一起。

每算一个阈值的正确率,就要往高低走统计,这样复杂度也是O(n^2),和暴力没区别。不过稍微改一下,就马上变O(n)。往高低走统计数量的时候其实有很多重复了的,比如有阈值[1,3,5,7],统计7的0的数量时候,往低处算要算上1,3,5的总数,统计5的时候,又要往前统计1,3的,重复很多,我们可以从1开始统计好总数记下来,3的时候用前面1的总数累加3自己的数,到5的时候,用3的累加5的数,就不用往前走了。
我们可以先用数组存好到达每个阈值的0的总数,计算某个阈值的0的总数时只需要用前面的总数加上本身0的数量即可,是一种动态规划。1同理,不过是从高分处开始计算。这样事先把每个阈值的低处0的总数和高处1的总数算出来后,就不用在计算某阈值准确率时往高低两边走,直接从数组中找到结果计算。
我这里直接在字典里加上变量了,没有用数组。

d = {
     }
m = int(input())
for i in range(m):
    y, res = map(int, input().split())
    if y in d:
        d[y][res] += 1
    else:
        # d[y]中,4个位置分别是
        # 挂了的数量,过了的数量,
        # 低分到这里的挂了的总数量,这里到高分的过了的数量
        d[y] = [0, 0, 0, 0]
        d[y][res] += 1

best, best_cnt = 0, 0
keys = sorted(d)  # 阈值升序排序

# 初始化头尾
d[keys[0]][2] = d[keys[0]][0]
d[keys[-1]][3] = d[keys[-1]][1]

# 累计,到该分数段,挂了的数量
for idx in range(1, len(keys)):
    key, pre_key = keys[idx], keys[idx - 1]
    d[key][2] = d[pre_key][2] + d[key][0]

# 累计,到该分数段,过了的数量
for idx in range(len(keys) - 2, -1, -1):
    key, pre_key = keys[idx], keys[idx + 1]
    d[key][3] = d[pre_key][3] + d[key][1]

# 计算每个阈值预测正确率,选出答案
for idx in range(len(keys)):
    key, pre_key = keys[idx], keys[idx - 1]
    # 小于该阈值的分数要0才是正确,大于等于的则1才正确
    cnt = d[key][2] - d[key][0] + d[key][3]
    if cnt > best_cnt:
        best_cnt = cnt
        best = key
    elif cnt == best_cnt and key > best:
        best = key

print(best)

# 7
# 0 0
# 1 0
# 1 0
# 1 0
# 3 0
# 5 0
# 7 0

你可能感兴趣的:(CCF)