题目链接
要想获得最大收益,那么卖出的商品应该尽可能晚,利润尽可能高,对此我们有两种方法,第一种是对过期时间进行排序,先处理过期时间短的商品;第二种是对商品利润进行排序,先处理利润高的商品。
方法一:优先队列
算法思路
按照过期天数从小到大进行排序,用一个优先队列来模拟需要卖出的商品,优先队列中的元素个数表示已经过去的天数。我们对排序后的商品列表进行遍历,若当前商品的过期时间大于队列中元素个数,说明售卖完队列中的商品后该商品依然不会过期,因此可以将此商品加入队列;若等于,则需要判断此商品的价值是否大于队头元素的利润(队头元素利润最低)。此外,并不会出现当前商品的过期时间小于队列中元素个数的情况,设当前商品的过期时间为n,则队列中的元素个数至少为n+1,那么队列中的最后一个元素的过期时间应至少为n+1,而过期天数由小到大进行排序,因此不可能出现此情况。
实现代码
import heapq as h
n = int(input())
ls = []
for i in range(n):
ls.append(list(map(int, input().strip().split())))
ls.sort(key=lambda x:x[1])
q = []
for goods in ls:
if goods[1] > len(q):
h.heappush(q, goods)
elif goods[1] == len(q):
if goods[0] > q[0][0]:
h.heappop(q)
h.heappush(q, goods)
ans = 0
for i in q:
ans += i[0]
print(ans)
方法二:并查集
算法思路
按照商品利润从大到小进行排序,然后依次卖出商品。商品可以在过期日期前任意一天卖出,为了保证不错过短过期时间的商品,我们尽可能晚地售卖商品。若当前商品的过期日期这天还没有商品卖出,那么就将该商品安排在这一天卖出;若当前商品的过期日期这天有商品卖出,则一定是之前利润更高的商品安排在这天卖出,因此我们需要将此商品安排在该日期之前售出,如果该日期前还有空余的日期,那么就在空余的日期售出,如果没有空余日期则不售出该商品。我们采用并查集的数据结构来实现此算法,设置一个日期并查集p,find(i)表示该日期前最晚能售卖的日期,初始时p[i]=i,表示该日期上没有商品售出,当第i天有商品售出时,则p[find(i)]应该等于find(i)-1,表示find(i)天后所有日期都有商品售卖。由于过期时间大于或等于商品个数的商品一定能售卖,因此我们不需要判断此类商品。
实现代码
def find(x):
if p[x] == x:
return x
else:
p[x] = find(p[x])
return p[x]
n = int(input())
ls, ans = [], 0
for i in range(n):
ls.append(list(map(int, input().strip().split())))
ls.sort(key=lambda x:x[0], reverse=True)
p = [i for i in range(n)]
for goods in ls:
if goods[1] >= n:
ans += goods[0]
continue
if find(goods[1]) > 0:
ans += goods[0]
p[find(goods[1])] = find(goods[1]) - 1
print(ans)