小Q在进行一场竞技游戏,这场游戏的胜负关键就在于能否能争夺一条长度为L的河道,即可以看作是[0,L]的一条数轴。
这款竞技游戏当中有n个可以提供视野的道具−真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在小Q想知道至少用几个真视守卫就可以覆盖整段河道。
输入描述:
输入包括n+1行。
第一行包括两个正整数n和L(1<=n<=105,1<=L<=109)
接下来的n行,每行两个正整数xi,yi(0<=xi<=yi<=109),表示第i个真视守卫覆盖的区间。
输出描述:
一个整数,表示最少需要的真视守卫数量, 如果无解, 输出-1。
输入例子1:
4 6
3 6
2 4
0 2
4 7
输出例子1:
3
============================================================================
(这道题自己踩雷了,还有一个无解的情况,题目说输出-1,读题仔细很重要)
算法思路
(1)首先要对所有守卫(x,y)根据x排序,对于最新选出的[xi, yi]最大延伸长度为yi;
(2)选出守卫的x小于xi的守卫,遍历查找哪个y延伸的最远
(3)得到新的[xj, yj]和最大延伸长度yj,返回(1)
题目要求的输入格式
a = list((map(lambda x:int(x), input().split())))
n, L = a[0],a[1]
eyes = []
for i in range(n):
eyes.append(list((map(lambda x:int(x), input().split()))))
模拟一个输入
n=11
L=28
eyes =[[0,3], [5, 24], [8, 27], [9, 19],
[3, 17], [13, 18], [9, 25], [19, 29],
[12, 15], [25, 29], [0, 6]]
方法1:按顺序迭代,每次都保存最新的延伸长度(case100%通过)
eyes.sort()
end = 0
max_length = 0
time = 1#需要的守卫,刚开始就要有一个
for i in range(n):
if max_length>=L:
break#长度达到退出
if eyes[i][0]>end:#如果中间空开了,比如【0,6】和【8,27】那么说明中间必有一个
time += 1#守卫数量+1
end = max_length
max_length = max(eyes[i][1], max_length)#***
elif eyes[i][1]>max_length: #如果和前一个仍然是重叠关系,且延伸长度更长,更新最大延伸长度
max_length = eyes[i][1]
print(time)
方法2:函数查找(case通过率50%,运行慢)
eyes.sort()
def eye_search(eye_y,eye_list):
length = [i[1]-eye_y for i in eye_list if i[0]<=eye_y]; turn = len(length)
choose = eye_list[length.index(max(length))]#被选中的孩子
return choose[1],eye_list[turn:]
eye_y=eyes[0][0]
eye_list = eyes
eye_time = 0
while len(eye_list)>0 and eye_y<L:
eye_time += 1
eye_y, eye_list = eye_search(eye_y=eye_y, eye_list=eye_list)
print(eye_time)
这道题有无解的情况,输出的时候要注意,这里就不写了,溜了。