【华为机试】工单题

这个问题一直放在我的 todo list里,今天还是靠陈博大佬给整出来了。

题目

大概意思是,有一批工单号,每个工单有一个时效SLA,也有一个得分score,每处理一个工单耗时一个单位。问应如何按时间处理这些工单号使得收益最大。
牛客网找的样例:
在这里插入图片描述
在这里插入图片描述

错误思路

在机试的时候立马想到的是优先处理快过期的,即按时间排序,时间相同的按得分降序。然后沿时间处理,累计得分。
但是样例一直只能通过45,百思不得其解,后来牛客网看到有大佬说下面这种情况
在这里插入图片描述
所以说并非每次优先处理即将过期的,因为可能有稍晚过期但得分高的工单,我们应该去处理这个高分工单【如 2 89】。

又错误思路

按奖励排序 --> 选出奖励最大的以及其时效 N --> 取所有小于等于该时效的TOP N --> 一次挑选结束,把所有小于该失效的都判为过期 -->重复去后面有效前内执行前面的步骤,直到最后时刻,退出循环

错误原因在于若得分次高的一些工单的SLA都为1,那么直接的TOP N将不成立

SLAS = list(map(int, input().split()))
scores = list(map(int, input().split()))
works = list(zip(SLAS, scores))

T = 0
ans = 0
works.sort(key=lambda x:x[1], reverse=True)
while works:
    t = works[0][0]
    N = t - T	## 可选工单数
    cnt = 0
    i = 0
    while cnt < N and i < len(works):
        if works[i][0] <= t:
            ans += works.pop(i)[1]
            cnt += 1
        else:
            i += 1
    works = [work for work in works if work[0]>t]	## 去除过期的工单
    T = t
print(ans)
## test 1
##1 1 3 3 2 2 6
##6 7 2 1 4 5 1

## test 2
##1 1 2 2 3
##7 5 89 100 6

正正正正解!!!

参考力扣630. 课程表 III
整体思路为:优先选择SLA小的,但若存在后面时间不够SLA但分数很高的单子,就要替换掉原来的选择。
具体的做法为:先按SLA排序,维护一个小根堆代表已经选的单。优先选SLA小的单子,当时间不够当前单时,当前单得分和已选单的最小得分pick,如果得分大则用该单子替换掉小得分单,否则忽略该单。这种做法能够一直保持当前时刻所选的所有单子得分和最大,即时刻保持最优解。

import heapq
SLAS = list(map(int, input().split()))
scores = list(map(int, input().split()))
works = list(zip(SLAS, scores))

works.sort(key=lambda x:x[0])
q = []
t = 0
ans = 0
for work in works:
    if work[0] > t:
        heapq.heappush(q, work[1])
        t += 1
        ans += work[1]
    else:
        minscore = heapq.heappushpop(q, work[1])
        ans += work[1] - minscore
print(ans)
## test 1
##1 1 3 3 2 2 6
##6 7 2 1 4 5 1

## test 2
##1 1 2 2 3
##7 5 89 100 6

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值