zoukankan      html  css  js  c++  java
  • 算法笔记(二):贪心算法

    (一)    贪心法

    贪心法在解决问题的策略上是根据当前已有的信息做出选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是某种意义上的局部最优。

    用贪心法求解的问题一般具有2个重要的性质:

    (1)   最优子结构:当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构。问题的最优子结构是该问题能采用贪心法求解的关键性质。

    (2)   贪心选择性质:指问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来得到。这也是贪心法和动态规划法的主要区别。

    (二)    示例1

    设有0,1,…,n-1个物品,体积分别为v0,v1,…,vn-1 ,将这些物品装入容量都为v的若干个箱子中,不同的装箱方案所需要的箱子数目可能不同,装箱问题要求使装尽这n种物品的箱子数最少。

    约定:

    (1)   物品体积不超过箱子容量。

    (2)   现有的箱子足以装入所有物品

    (3)   物品不能拆分

    算法描述:

    输入物品列表信息

    输入箱子列表信息

    将物品列表按体积降序排序(从大到小)

        while 还有物品未装入箱子:

            if 物品体积 <= 箱子容量:

                 将物品装入箱子

                 更新箱子容量

                 物品列表中移除已经装入箱子的物品

             else:(如果当前箱子不足以装入物品)

                  获取下一个箱子的索引

     1 import random
     2 import operator
     3 #物品类
     4 class goods():
     5     def __init__(self,goods_name,goods_v):
     6         self.goods_name = goods_name #物品名称
     7         self.goods_v = goods_v   #物品体积
     8 #箱子类
     9 class box():
    10     def __init__(self,box_name):
    11         self.box_name = box_name #箱子名称
    12         self.box_v = 50  #箱子容量
    13 
    14 #贪心算法实现,goods_list:物品列表  box_list:箱子列表
    15 def greedy(goods_list,box_list):
    16     cmpfun = operator.attrgetter('goods_v')
    17     goods_list.sort(key=cmpfun, reverse=True)  # 将物品列表按体积降序排序
    18     i = 0 #物品列表索引(下标)
    19     j = 0 #箱子列表索引(下标)
    20     box_count = 0 #初始化箱子使用数量
    21     while goods_list:
    22         if goods_list[i].goods_v <= box_list[j].box_v:
    23             print('将物品:'+str(goods_list[i].goods_name)+"    装入箱子:", box_list[j].box_name)
    24             #更新箱子容量
    25             box_list[j].box_v = box_list[j].box_v - goods_list[i].goods_v
    26             j = 0
    27             del goods_list[i] #从物品列表中移除已经装入箱子的物品
    28         else:
    29             j += 1
    30             if box_count < j :
    31                 box_count = j
    32      # 因为索引从0开始的,所以这里+1后得到箱子使用数量
    33     print('最终使用箱子数:',box_count+1)
    34     return box_list
    35 
    36 goods_list = []
    37 #初始化10个物品
    38 for i in range(10):
    39     goods_name = "物品%s"%i
    40     goods_v = random.randint(1,50)
    41     goods_list.append(goods(goods_name,goods_v))
    42 
    43 box_list = []
    44 #初始化10个箱子
    45 for i in range(10):
    46     box_name = "箱子%s"%i
    47     box_list.append(box(box_name))
    48 
    49 box = greedy(goods_list,box_list)
    50 print("箱子使用情况:")
    51 for i in box:
    52     print(i.box_name + '  剩余容量:' + str(i.box_v))

     

    (三)    示例2(0-1背包问题)

    现在商店有0,1,…,n件商品,体积分别为V0,V1,…,Vn ,价值分别为P0,P1,…,Pn ,假设背包容量为V,现在要求使背包装入商品的价值最大化。

    约定:

    (1)   背包不足以装入所有物品。

    (2)   每个商品,要么完整装入,要么放弃该商品,不能只装入商品的一部分。

    算法描述:

        输入商品列表信息

        输入背包容量

        将商品列表按单位价值降序排序(就是性价比,例如:每斤值多少钱)

        while 还有商品未装入背包(或者未排除):

            if  商品体积小等于背包剩余容量:

                  将商品装入背包

                  更新背包剩余容量

                  在商品列表中移除已经装入背包的商品

            else:(如果背包剩余容量不足以装入商品)

                  在商品列表中移除不能装入背包的商品

     1 import random
     2 import operator
     3 #商品类
     4 class goods():
     5     def __init__(self,goods_name,goods_v,goods_p):
     6         self.goods_name = goods_name #商品名称
     7         self.goods_v = goods_v   #商品体积
     8         self.goods_p = goods_p   #商品总价值
     9         self.value = self.goods_p/self.goods_v #商品单位价值
    10 
    11 #贪心算法实现,goods_list:商品列表 V:背包剩余容量 result_list:存放最终装入背包的商品
    12 def greedy(goods_list,V,result_list):
    13     cmpfun = operator.attrgetter('value')
    14     goods_list.sort(key=cmpfun,reverse=True) #将商品列表按单位价值降序排序
    15     #打印排序后的所有商品信息,这里为方便看效果,实际可以去掉这个
    16     for goods in goods_list:
    17         print(goods.goods_name +"  体积:"+str(goods.goods_v)+"  价值:" + str(goods.goods_p) + "  单位价值:" +str(goods.value))
    18     while goods_list and V > 0:
    19         i = 0
    20         #如果商品体积小等于背包容量
    21         if goods_list[i].goods_v <= V:
    22             #将商品放入背包
    23             result_list.append(goods_list[i])
    24             #更新背包剩余容量
    25             V = V - goods_list[i].goods_v
    26             #在列表中删除该商品
    27             del goods_list[i]
    28         else:
    29             del goods_list[i]
    30     print('背包剩余空间',V)
    31     return result_list
    32 
    33 
    34 V = 100 #初始化背包容量
    35 goods_list = []
    36 #初始化1000个商品
    37 for i in range(1000):
    38     goods_name = "商品%s"%i
    39     goods_v = random.randint(1,100)
    40     goods_p = random.randint(1,100)
    41     goods_list.append(goods(goods_name,goods_v,goods_p))
    42 result_list = []
    43 result = greedy(goods_list,V,result_list)
    44 print("最终装入背包的商品:",end='')
    45 for i in result:
    46     print(i.goods_name + ",",end='')

  • 相关阅读:
    lxml.etree 教程5:Using XPath to find text
    .Net程序员学习Linux最简单的方法
    海南航空宁波到重庆的"变态"机票
    《帮我买单》帮我买单的故事
    VS 2005 Beta2 Team版正在下载中
    安家博客园
    标记:Oracle里面的过程两种参数的不同
    今天搞VS 2005搞了半天没真正搞出个什么名堂来
    Oracle中INSTR方法
    今天可算把VS 2005 Beta2安装上了,赶紧体会体会
  • 原文地址:https://www.cnblogs.com/simple-free/p/9068598.html
Copyright © 2011-2022 走看看