202012-2 期末预测之最佳阈值(一维前缀和)(最详细题解)

202012-2 期末预测之最佳阈值

总结:

在这里插入图片描述

这道题看似不难,但同比于历年的第二题来说,虽然求解不能但是想难满分却实属不易,笔者一开始抱着看似简单的心态,用暴力O(n**2)做完后,却遭到了运行超时的滑铁卢,最后查阅许多算法类资料,才将算法优化,最后运行通过,下面我将详细讲解本题以及读者可能出现的问题答疑。

注意:

  • 若为70 分,且显示运行超时,说明需要优化算法
  • 若为70分,显示运行错误时,则很有可能使用了递归法导致内存占用太大无法运行后面30%的测试集导致的,笔者一开始也是满脑墨水,百思不知其解。

1. 题目介绍

2. Python代码及题目分析

1. 思路:

  1. 题目要求计算每一个y所对应的预测正确次数,将次数最多的y记为O。
  2. 我们需要计算每一个y的预测正确次数,一般情况大家都可以想到利用双层for进行遍历求次数,但是这样只能拿70分,所以这里利用动态规划的思路,用空间换取时间---------前缀和算法
    1. 先统计所有y正确预测不及格的次数
    2. 再统计所有y正确预测及格的次数
  3. 二者相加即为所有y正确预测的次数
  4. 最后将其按照预测次数由大到小依次排列
  5. 最后将所求的O输出。

2. 具体分析:

1.想将测试集的数据输入到我们的程序之中

m = int(input())  # m 位同学
y_result = [0] * m  # m位同学的信息
counts = {}  # 预测正确次数集合
for i in range(m):# 遍历将m个同学信息输入
    y_result[i] = list(map(int, input().split()))
  1. 利用前缀和算法分别计算:
    1. 先统计所有y正确预测不及格的次数
    2. 再统计所有y正确预测及格的次数
  • 前缀和算法:
    • 前提条件:必须为有序数对
    • 此题中我们不能发现,当求下一个数据正确预测不及格的次数的时候,他想当于是在前一个数据所求的次数基础上再进行增加的,所以没当我们求出一个y对应的正确预测不及格次数count时,我们就将其放入事先创建好的less_counts{}字典中,这样在求下一个数时就不用从头求了,直接调用字典里存在再进行增加即刻,具体思路见代码。
# 其预测为挂科正确的次数
y_result.sort(key=lambda x: x[0])  # 为了使用前缀和优化,选择将信息按y进行排序
less_counts = {}
less_count = 0
for i in range(m):
    o_i = y_result[i][0]  # 此次的y
    o_j = y_result[i - 1][0]  # 前一次的y
    result = y_result[i-1][1]  # 本次的挂科情况
    if i - 1 == -1:
        less_counts[o_i] = less_count
        continue
    if o_i >= o_j and result == 0:
        less_count += 1
    if o_i > o_j : # y不相等时候才要记录
        less_counts[o_i] = less_count
        less_count = 0
        if o_i in less_counts:
            less_count = less_counts[o_i]
# 求预测不挂科正确的次数
y_result_r = list(reversed(y_result))
more_counts = {}
for i in range(m):
    o_i = y_result_r[i][0]  # 此次的y
    o_j = y_result_r[i - 1][0]  # 前一次的y
    result = y_result_r[i][1]  # 本次的挂科情况
    more_count = 0
    if o_j in more_counts:
        more_count = more_counts[o_j]
    if i - 1 == -1:
        if result == 1:
            more_count = 1
        more_counts[o_i] = more_count
        continue
    if o_i <= o_j and result == 1:
        more_count += 1
    # y相等时候也要记录
    more_counts[o_i] = more_count
  1. 统计完及格次数和不及格次数后我们在利用标准库collections模块中的counter类将,相同key的value相加,求得我们最终所要的正确次数的字典。
  • 注意:当相加时会以左边的key为标准进行相加,由于我们要输入相同次数下,y大的作为O,所以我们将刚刚倒序所求的more_counts做为左边,即相加时的标准。
Less_counts , More_counts = Counter(less_counts),Counter(more_counts)
counts = dict(More_counts+Less_counts)

4 . 找到最大的counts,并以其为判断条件求出我们要的y,即倒序状态下第一个取值为countmax的y。

countmax = max(counts.values())
for count in counts:
    if counts[count] == countmax:
        print(count)
        break

3. 整体代码

from collections import Counter
m = int(input())  # m 位同学
y_result = [0] * m  # m位同学的信息
counts = {}  # 预测正确次数集合
for i in range(m):
    y_result[i] = list(map(int, input().split()))

# 利用前缀和进行算法优化,不然会超时
# 其预测为挂科正确的次数
y_result.sort(key=lambda x: x[0])  # 为了使用前缀和优化,选择将信息按y进行排序
less_counts = {}
less_count = 0
for i in range(m):
    o_i = y_result[i][0]  # 此次的y
    o_j = y_result[i - 1][0]  # 前一次的y
    result = y_result[i-1][1]  # 本次的挂科情况
    if i - 1 == -1:
        less_counts[o_i] = less_count
        continue
    if o_i >= o_j and result == 0:
        less_count += 1
    if o_i > o_j : # y不相等时候才要记录
        less_counts[o_i] = less_count
        less_count = 0
        if o_i in less_counts:
            less_count = less_counts[o_i]
# 求预测不挂科正确的次数
y_result_r = list(reversed(y_result))
more_counts = {}
for i in range(m):
    o_i = y_result_r[i][0]  # 此次的y
    o_j = y_result_r[i - 1][0]  # 前一次的y
    result = y_result_r[i][1]  # 本次的挂科情况
    more_count = 0
    if o_j in more_counts:
        more_count = more_counts[o_j]
    if i - 1 == -1:
        if result == 1:
            more_count = 1
        more_counts[o_i] = more_count
        continue
    if o_i <= o_j and result == 1:
        more_count += 1
    # y相等时候也要记录
    more_counts[o_i] = more_count

Less_counts , More_counts = Counter(less_counts),Counter(more_counts)
counts = dict(More_counts+Less_counts)
countmax = max(counts.values())
for count in counts:
    if counts[count] == countmax:
        print(count)
        break

3.测试结果:

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

  • 总结:小白刚刚接触csp,若代码算法关于简单,过于暴力望谅解
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿明同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值