文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

贪心算法①--使用贪心算法思想解活动安排问题-python

2023-10-26 11:01

关注
'''一、具有贪心选择结构    复杂问题可以划分成小问题解决二、具有贪心选择性质    是否能够用贪心选择开始一个最优起点,使用贪心选择能否得到一个完整解案例1:最优装载问题    有n个集装箱需要装上一艘重量为W的轮船。    其中,集装箱i(i=1,2,3....n)的重量Wi。    最优装载问题要求在确定转载体积不受限制的情况下,怎么样    装才可以尽可能多的把集装箱装上轮船?    1.贪心选择结构    sum(Wi) = W    假设已经把第一个集装箱装上轮船了,此时该集装箱的重量为W1,    轮船重量为W,剩余轮船可以装的重量W - W1.    当装到i个集装箱的时候,满足:    Wy = W(总问题) - Wi(子问题)    Wy + Wi(子问题) = W(总问题)案例2:活动安排问题    有n个活动需要安排在礼堂举行,每个活动有编号、开始时间、结束时间,    请您去安排本次活动,在有限时间内尽量多的安排活动?    n个活动n1 n2 n3    meetings = [(2,1,4),(4,5,7),(1,3,6),(3,2,8),(5,4,7),(6,6,9)]    比如礼堂开放的时间是:0-7点     1.最优子结构性质?能不能拆 -->能拆就可以使用两种算法:贪心算法和动态规划(重叠子问题)     3 1 0.8 0.5 0.1     4.6 = 3 + 1 + 0.5 + 0.1     2.贪心选择性质        2.1  i2 + i1 + i4 + i5 + i6=5(假设是最好的)        2.2 以一个最优的选择i2开始活动安排三种思路:    a开始时间早的活动优先安排;    b结束时间早的活动优先安排;    c使用时间短的活动优先安排。    班级      开始时间--结束时间      活动1    1班      8:00-12:00          上课2    2班      8:30-10:30           讲座3    3班      11:00-11:30          开会4    4班      10:40-11:20          竞选活动整个教室开放时间是0-24:最优方案就是:3可以选择贪心-->怎么组合才能解出此题?方案b,2-->4-->3-->1方案a,1-->2-->4-->3.元祖有三个参数,第一个表示活动编号,第二个表示活动开始时间,第三个表示活动结束时间meetings = [    (1,3,6),    (2,1,4),    (3,5,7),    (4,2,5),    (5,5,9),    (6,3,8),    (7,8,11),    (8,6,10),    (9,8,12),    (10,12,14)]三种思路:    a开始时间早的活动优先安排;    b结束时间早的活动优先安排;    c使用时间短的活动优先安排。方案b(结束时间早):2--> 3 -->7 -->10方案a(开始时间早):2--> 3 -->7 -->10方案c(用时最短)  :3-->10满足:最优子结构 && 贪心选择性质(2号在当前是最优选择),此题可以使用贪心算法求解,并且能够求到一个最优解或近似最优解'''# 测试数据# meetings = [#     (1, 3, 6),#     (2, 1, 4),#     (3, 5, 7),#     (4, 2, 5),#     (5, 5, 9),#     (6, 3, 8),#     (7, 8, 11),#     (8, 6, 10),#     (9, 8, 12),#     (10, 12, 14)# ]

Python详细解:

meetings = [    (4, 1, 4),    (2, 3, 5),    (1, 0, 6),    (5, 5, 7),    (7, 3, 8),    (8, 5, 9),    (9, 6, 10),    (3, 8, 11),    (10, 8, 12),    (11, 2, 13),    (6, 12, 14)]# 贪心算法过程def eventArrangement(m):    # 活动总数    # n = 0    # for i in m:    #     n += 1    n = len(m)    # print(n)    '''    按照活动结束时间对活动进行升序排列-活动结束时间早的排在前面使其满足贪心选择性质    推荐使用方法一:    方法一:此处选用冒泡排序方法,提供冒泡排序的口诀:    冒泡口诀:        n数来冒泡,        两两相比较。        外层循环n-1,        内层循环n-1-i。        上上下下,左右右左,BABA    得到的排序结果如下:    [(2, 1, 4), (4, 2, 5), (1, 3, 6), (3, 5, 7), (6, 3, 8), (5, 5, 9), (8, 6, 10), (7, 8, 11), (9, 8, 12), (10, 12, 14)]        复杂度 < Log2n    '''    # 双层循环为了构造出一对多的比较,如i=1的时候,j分别是从0到n-i-1的    for i in range(n - 1):        for j in range(n - i - 1):            '''            前后元素比较大小,j与j+1构造出前后元素进行比较:            m[j]和m[j + 1]是构造出前后两个元素,由于得到的元素是元组类型,            因此使用m[j][2]和m[j + 1][2]获取到活动结束时间            '''            if m[j][2] >= m[j + 1][2]:                # 执行元素交换,而不是活动结束时间交换                m[j], m[j + 1] = m[j + 1], m[j]    '''    方法二:    调用系统提供的排序函数sort(),只是消耗的排序复杂度略高。    m.sort(key = lambda x:x[2])    得到的排序结果如下:    [(2, 1, 4), (4, 2, 5), (1, 3, 6), (3, 5, 7), (6, 3, 8), (5, 5, 9), (8, 6, 10), (7, 8, 11), (9, 8, 12), (10, 12, 14)]    复杂度 >= Log2n    '''    # m.sort(key=lambda x: x[2])    # print(m)    # 定义一个标志位列表,初始化时其中的值置为False表示所有活动在初始时均未被安排,后续满足条件被选中时置为True即可    meetingsFlag = [False for i in range(n)]    # print(meetingsFlag)    # j = 0是为了满足贪心选择性质,默认选中第0号活动,由于升序排列,第0号活动是当前这一步中最优解(结束时间最早的活动)    j = 0    # 由于已经选择了这一个活动,将其标志位置为True,也满足贪心选择走出当前这一步以后不允许回退的原则    meetingsFlag[j] = True    '''    此处的自变量i是从1开始的,意味着i默认是选择候选活动中的第1号活动,因为0号活动已经被选择.    所以此时j=0表示第0号活动,i=1表示1号活动,也正好构造了前一个活动与后一个活动,为下面的活动比较构造好了比较序列    '''    for i in range(1, n):        '''        如果后一个活动的开始时间是晚于前一个活动的结束时间的,说明后一个活动可以被选择:        m[i]表示后一个活动,m[i][1]表示后一个活动的开始时间,因为m[i]是个元组,如(1, 3, 6),        那么m[i][1]得到的是元组中第二个元素就是3,3表示的是1号活动的开始时间是3点.                m[j]表示前一个被选择的活动,m[j][2]表示前一个活动的结束时间.如(3, 5, 7),那么m[j]是当前这个元组        (3,5,7),m[j][2]是元组中的第三个元素7,表示上一个活动结束时间.                因此,此处构造了前一个活动的结束时间与下一个候选活动的开始时间进行比较.        '''        if m[i][1] >= m[j][2]:  # 若满足表示后一个活动可以安排            # 将j的值更新为当前已经被选中的活动i            j = i            # 因此将可以安排的这个活动的标志位改为True,标志着它已经被选中了            meetingsFlag[j] = True    '''        循环结束表示此时活动已经安排完成,那就根据题目要求来灵活处理,若是需要统计有多少个活动被选择,那就直接统计        meetingsFlag列表中有多少个True即可,若需要统计是哪些具体活动被选择了,就需要将被选择的活动进行输出    '''    return meetingsFlagdef output():    # 函数调用    resulst = eventArrangement(meetings)    n = 0    for i in resulst:        n += 1    print(resulst)    # 统计有多少活动被选择    changeCount = 0    '''    统计具体是哪一些活动被选择了:    1.通过遍历标志位中为True的元素获取其下标,这个下标同时也是候选集活动meetings中的当前活动的下标    2.通过此下标去候选集meetings中获取到被选中的活动    '''    for i in range(n):        if resulst[i]:            print('第' + str(meetings[i][0]) + '号活动被安排。')            changeCount += 1  # 计数器+    print('共计:' + str(changeCount) + '个活动被选择。')# 函数调用output()

Python精简解:

def m(meetings):    length = len(meetings)    meetings.sort(key=lambda x: x[2])    result = [False for i in range(length)]    j = 0    result[j] = True    for i in range(1, length):        if meetings[i][1] >= meetings[j][2]:            j = i            result[j] = True    return resultmeetings = [(4, 1, 4), (2, 3, 5), (1, 0, 6), (5, 5, 7), (7, 3, 8), (8, 5, 9), (9, 6, 10), (3, 8, 11), (10, 8, 12),            (11, 2, 13), (6, 12, 14)]result = m(meetings)print(result)

来源地址:https://blog.csdn.net/lishihuijava/article/details/133181939

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯