贪心算法:挑选过程是多部判断,每步依据“短视”的策略进行活动选择,算则是注意满足相容性条件。
问题
输入S={1,2,3,···,n}为n项活动的集合,si和fi分别是第i个活动的开始时间和结束时间。
活动i与活动j相容,活动i在活动j结束之前,或者活动j在活动i结束之前,si>=sj或sj>=si
求:最大的两两相容集A
i(第i个活动) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
si(开始时间) | 1 | 3 | 0 | 5 | 3 | 5 | 6 | 8 | 8 | 2 |
fi(结束时间) | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
使用贪心算法:
伪码
输入:A∈S 选中的活动子集
n←lenth[s] n为原始集合输入个数
A←{1} 初始把1挑入集合中
j←1 j记录的是跳到A中的最大活动标号
for i←2 to n do
if si>=fj 开始时间大于结束时间
than A←A∪{i} 把第i个活动放入集合A中
j←i
return A
活动结束时间为: t=max{fk:k∈A}
时间复杂度为:o(nlogn) = o(nlogn) + o(n) o(nlogn)为结束时间排序,o(n)第一轮挑选
代码
i = [1,2,3,4,5,6,7,8,9,10]
si = [1,3,0,5,3,5,6,8,8,2]
fi = [4,5,6,7,8,9,10,11,12,13]
def greed():
n = len(i)
# 把初始值放入A中
A = [i[0]]
# j记录的是放入A中的最大活动标
j = i[0]-1
for a in i:
# 防止数组超出
if a==n:
break
# 开始时间大于结束时间
if si[a]>=fi[j]:
# 由于数组下标是从0开始的所以输出时需要加1
A.append(a+1)
j=a
print(A)
if __name__ == '__main__':
greed()