惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog
Microsoft Security Blog
Microsoft Security Blog
Jina AI
Jina AI
博客园 - 叶小钗
J
Java Code Geeks
博客园 - 聂微东
博客园 - 司徒正美
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
美团技术团队
WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
罗磊的独立博客
T
The Blog of Author Tim Ferriss
aimingoo的专栏
aimingoo的专栏
T
Tailwind CSS Blog
The Cloudflare Blog
Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
小众软件
小众软件

博客园 - StudyNLP

python把中文汉字转拼音,存储到excel表格 算法结束篇 贪心-钓鱼问题 贪心-放置雷达 贪心-电影节 贪心-圣诞老人的礼物 广度优先搜索-八数码问题 广度优先搜索-鸣人和佐助 广度优先搜索-迷宫问题 广度优先搜索-抓住那头牛 深度优先搜索-生日蛋糕 深度优先搜索-Roads 深度优先搜索-踩方格 深度优先搜索-城堡问题 动态规划-分蛋糕V2 动态规划-分蛋糕V1 动态规划-滑雪 动态规划-0-1背包问题 动态规划-神奇的口袋V2
贪心-Stall Reservations
StudyNLP · 2020-08-05 · via 博客园 - StudyNLP
问题:有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()