算法笔记(二):贪心算法

(一)    贪心法

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

用贪心法求解的问题一般具有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='')

 

posted @ 2018-05-22 18:39  free赖权华  阅读(421)  评论(0编辑  收藏  举报