【专题】贪心算法
一:区间问题
1、线段覆盖
现在各大 oj 上有 n 个比赛,每个比赛的开始、结束的时间点是知道的。
yyy 认为,参加越多的比赛,noip 就能考的越好。所以,他想知道他最多能参加几个比赛。
由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同一时间参加 2 个及以上的比赛。
python
n=int(input())
intervals=[list(map(int,input().split())) for _ in range(n)]
# 按右端点排序,贪心选择最早结束的区间
end_intervals=sorted(intervals,key=lambda x:x[1])
end = -1
count=0
for interval in end_intervals:
if interval[0] >= end:
count += 1
end=interval[1]
print(count)
----------------------------------
输入:
3
0 2
2 4
1 3
输出:2
----------------------------------
2、答疑
有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。
老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下:
- 首先进入办公室,编号为 i 的同学需要 si 毫秒的时间。
- 然后同学问问题老师解答,编号为 i 的同学需要 ai 毫秒的时间。
- 答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可以忽略。
- 最后同学收拾东西离开办公室,需要 ei 毫秒的时间。一般需要 10 秒、20 秒或 30 秒,即 ei 取值为 10000,20000 或 30000。
一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
答疑从 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群 里面发消息的时刻之和最小。
python
n=int(input())
students=[list(map(int,input().split())) for _ in range(n)]
# 按总体消耗时间排序
new_students=sorted(students,key=lambda x:(sum(x)))
sums=0
temp=0
for i in range(n):
sums=sums+temp+new_students[i][0]+new_students[i][1]
temp+=sum(new_students[i])
print(sums)
------------------------------------
输入:
3
10000 10000 10000
20000 50000 20000
30000 20000 30000
输出:280000
------------------------------------
二:分配问题
1、部分背包
题型 :物品可分割,求最大价值
。
阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N (N ≤100) 堆金币,第 i 堆金币的总重量和总价值分别是 mi,vi(1≤mi,vi≤100)。阿里巴巴有一个承重量为 T (T ≤1000) 的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?
python
n,t=list(map(int,input().split()))
product=[list(map(int,input().split())) for _ in range(n)]
values = 0
# 算出每个单位值多少钱,用此换掉每个物品总价值
for i in range(n):
product[i][1] = product[i][1] / product[i][0]
sort_product=sorted(product,key=lambda x:-x[1])
for i in range(n):
while sort_product[i][0]!=0 and t!=0:
values+=sort_product[i][1]
t-=1
sort_product[i][0]-=1
print("%.2f" % values)
2、快乐司机
这是儿歌"快乐的小司机"。话说现在当司机光有红心不行,还要多拉快跑。多拉不是超载,是要让所载货物价值最大,特别是在当前油价日新月异的时候。司机所拉货物为散货,如大米、面粉、沙石、泥土 ⋯⋯
现在知道了汽车核载重量为 w,可供选择的物品的数量 n。每个物品的重量为 gi, 价值为 pi。求汽车可装载的最大价值。
python
n,w=list(map(int,input().split()))
goods=[list(map(int,input().split())) for _ in range(n)]
for i in range(n):
g,p=goods[i]
# 添加一项,每重量多少价值(钱/重量)
goods[i]=[p/g,g,p]
new_goods=sorted(goods,key=lambda x:-x[0])
weight=w # 总重量
values=0 # 总价值
flag=0
for i in range(n):
if flag==1:
break
while new_goods[i][1]!=0:
if weight<=0:
flag=1
break
else:
weight-=1 # 总重量减去一个物品单元重量
new_goods[i][1]-=1 # 当前物品数量减去1
values+=new_goods[i][0] # 总价值加上单元物品价值【每重量多少价值】
print("%.1f" % values)
----------------------------------------
输入:
5 36
99 87
68 36
79 43
75 94
7 35
输出:
71.3
----------------------------------------