使用贪心python算法解决背包问题

Posted

技术标签:

【中文标题】使用贪心python算法解决背包问题【英文标题】:Solving knapsack problem using a greedy python algorithm 【发布时间】:2018-10-05 20:20:25 【问题描述】:

我正在尝试使用 Python 解决背包问题,实现贪心算法。我回来的结果对我来说毫无意义。

背包:

第一行给出了物品的数量,在本例中为 20。最后一行给出了背包的容量,在本例中为 524。其余行给出了每个项目的索引、价值和重量。

20
    1    91    29
    2    60    65
    3    61    71
    4     9    60
    5    79    45
    6    46    71
    7    19    22
    8    57    97
    9     8     6
   10    84    91
   11    20    57
   12    72    60
   13    32    49
   14    31    89
   15    28     2
   16    81    30
   17    55    90
   18    43    25
   19   100    82
   20    27    19
524

Python 代码:

import os 

def constructive():     
    knapsack = []
    Weight = 0
    while(Weight <= cap):
        best = max(values)
        i = values.index(best)
        knapsack.append(i)
        Weight = Weight + weights[i]
        del values[i]
        del weights[i]
    return knapsack, Weight


def read_kfile(fname):
    with open(fname, 'rU') as kfile:
        lines = kfile.readlines()     # reads the whole file
    n = int(lines[0])
    c = int(lines[n+1])
    vs = []
    ws = []
    lines = lines[1:n+1]   # Removes the first and last line
    for l in lines:
        numbers = l.split()   # Converts the string into a list
        vs.append(int(numbers[1]))  # Appends value, need to convert to int
        ws.append(int(numbers[2]))  # Appends weigth, need to convert to int
    return n, c, vs, ws

dir_path = os.path.dirname(os.path.realpath(__file__))  # Get the directory where the file is located
os.chdir(dir_path)  # Change the working directory so we can read the file

knapfile = 'knap20.txt'
nitems, cap, values, weights = read_kfile(knapfile)
val1,val2 =constructive()
print ('knapsack',val1)
print('weight', val2)
print('cap', cap)

结果:

knapsack [18, 0, 8, 13, 3, 8, 1, 0, 3]
weight 570
cap 524

【问题讨论】:

【参考方案1】:

欢迎。您的程序给出的权重超过上限的原因是因为在您放入背包的最后一件物品上,您没有检查它是否可以放入其中。为此,只需添加一个 if 语句,您还应该检查值列表是否为空。请注意,我已附加 (i+1),因为您的文本文件的索引从 1 开始,但 Python 的列表索引从 0 开始:

def constructive():
    knapsack = []
    Weight = 0

    while(Weight <= cap and values):
        best = max(values)
        i = values.index(best)
        if weights[i] <= cap-Weight:
            knapsack.append(i+1)
            Weight = Weight + weights[i]
        del values[i]
        del weights[i]

    return knapsack, Weight

【讨论】:

【参考方案2】:

问题是 -- 在最后一步 -- 您找到的最佳物品将超过最大重量。但是由于您已经进入了循环,所以无论如何都要添加它。 在下一次迭代中,您意识到自己已经超出上限并停止。

我不确定一旦次优太重,你想如何进行。如果您只是想停止而不添加任何内容,您可以简单地修改您的 constructive 如下所示:

def constructive():

    knapsack = []
    Weight = 0

    while(True):
        best = max(values)
        i = values.index(best)

        if Weight + weights[i] > cap:
            break

        knapsack.append(i)
        Weight = Weight + weights[i]

        del values[i]
        del weights[i]

    return knapsack, Weight

【讨论】:

以上是关于使用贪心python算法解决背包问题的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法:背包问题

关于旅行家TSP问题的几种算法 python

算法贪心算法(0-1背包问题)

贪心算法解决背包问题?

0-1背包的贪心算法

python_分治算法贪心算法动态规划算法