贪心-Stall Reservations

问题:有n 头牛( 1<=n<=50,000) 要挤奶。给定每头牛挤奶的时间区间 [A,B]
(1<=A<=B<=1,000,000 A,B 为整数 。牛需要呆畜栏里才能挤奶。
一个畜栏同一时间只能容纳一头牛。问至少需要多少个畜栏,才能完成全部挤奶工作,
以及每头牛都放哪个畜栏里( Special judged)去同一个畜栏的两头牛,
它们挤奶时间区间哪怕只在端点重合也是不可以的。
现在农场主希望知道最少几个畜栏能满足上述要求,并要求给出每头牛被安排的方案。
对于多种可行方案,主要输出一种即可。

输入:
输入的第一行包含一个整数N(1 ≤ N ≤ 50, 000),表示有N牛头;接下来N行
每行包含两个数,分别表示这头牛的挤奶时间[Ai, Bi](1≤A≤B≤1,000,000)。
输出:
输出的第一行包含一个整数,表示最少需要的畜栏数;接下来N行,第i+1行描述了
第i头牛所被分配的畜栏编号(从1开始)。

样例输入
5
1 10
2 4
3 6
5 8
4 7
样例输出
4
1
2
3
2
4

思路:贪心解法,所有奶牛都必须挤奶。到了一个奶牛的挤奶开始时间,就必须为这个奶
牛找畜栏。因此按照奶牛的开始时间逐个处理它们,是必然的。S(x)表示奶牛x的开始时间。
E(x) 表示 x 的结束时间。对 E(x), x 可以是奶牛,也可以是畜栏。
畜栏的结束时间,就是正在其里面挤奶的奶牛的结时间。
同一个畜栏的结束时间是不断在变的。

1)把所有奶牛按开始时间从小到大排序。
2)为第一头奶牛分配一个畜栏。
3)依次处理后面每头奶牛i。处理 i 时,考虑已分配畜栏中,结束时间最早的畜栏x。
若E(x) < S(i), 则不用分配新畜栏,i可进入x,并修改 E(x)为 E(i)
若E(x) >= S(i),则分配新畜栏 y,记 E(y) = E(i)
直到所有奶牛处理结束
需要用优先队列存放已经分配的畜栏,并使得结束时间最早的畜栏始终位于队列头部。
从第一头奶牛开始,第一头奶牛肯定放进第一个牛栏里,之后每个奶牛都是与牛栏中
结束时间最早的那个相比,如果可以放进去,就放进去啦,如果不能放进去,就重新开一个牛栏

由于按开始时间的顺序处理奶牛是必然,且按该算法,为奶牛
i 分配新畜栏时,确实是不得不分配的,所以算法正确。

python代码实现:
from queue import PriorityQueue


def main():
    # 输入牛的列表,0:起始时间,1:结束时间,2:牛的编号
    cow_list = []
    # 总共需要的畜栏
    total = 0
    # i表示编号为i的奶牛去的畜栏编号
    pos = [0 for i in range(10)]
    # n头牛
    n = int(input())
    for i in range(1, n+1):
        temp = list(map(int, input().split()))
        temp.append(i)
        cow_list.append(temp)
    cow_list = sorted(cow_list, key=lambda x: x[0])
    # 按开始时间排序后的列表
    # [[1, 10, 1], [2, 4, 2], [3, 6, 3], [4, 7, 5], [5, 8, 4]]
    # pq优先权队列中元素是list,0:结束时间,1:畜栏编号
    pq = PriorityQueue()
    for i in range(n):
        if pq.empty():
            total += 1
            pq.put([cow_list[i][1], total])
            pos[cow_list[i][2]] = total
        else:
            # 获取pq队列中结束时间最早的列表st
            # st = pq.get()
            # 此处很重要,如果使用get会把队头元素删除,使用queue属性,则会返回
            # 整个队列元素的列表,为了去队头,所以索引是0
            st = pq.queue[0]
            # 队列中最早结束时间小于新加入这头牛的开始时间
            if st[0] < cow_list[i][0]:
                pos[cow_list[i][2]] = st[1]
                pq.put([cow_list[i][1], st[1]])
            # 新增加一个牛栏
            else:
                total += 1
                pq.put([cow_list[i][1], total])
                pos[cow_list[i][2]] = total

    print("最少需要的畜栏数:%d" % total)
    for i in range(1, n+1):
        print("%d" % pos[i])

    return 0


if __name__ == '__main__':
    main()

 

 
posted @ 2020-08-05 10:05  StudyNLP  阅读(224)  评论(0编辑  收藏  举报