如何通过数量和重量限制最大化携带宝石的价值?

时间:2017-05-10 11:40:05

标签: algorithm knapsack-problem

假设你有100颗珍贵的宝石,每颗宝石的重量从0到100,每个宝宝的价值可以是任何正数。你只能携带5个,总重量不能超过30个。

如何选择要携带的宝石会产生最大值?

目前,我的项目中有一个类似的情况,我通过蛮力解决它。有更快的方法吗?

4 个答案:

答案 0 :(得分:3)

这是一个非常常见的算法挑战,称为背包问题,最好通过动态编程解决:

https://en.wikipedia.org/wiki/Knapsack_problem

答案 1 :(得分:1)

参考0-1背包问题。 Wiki

答案 2 :(得分:1)

为什么天真的宝石分类方法和选择最重的宝石的原因不是因为最重的宝石可能没有最大的价值。这就是为什么需要背包算法的原因:它选择由选择宝石或不选择宝石而产生的最大值。下一个宝石或宝石可能具有比当前宝石更大的价值。递归背包解决方案就像:

def knapsack(weights, values, capacity, m, count):
    # if no more gems to examine or already chosen 5 gems
    if (m == 0 or count == 5):
        return 0

    # If the gem weight is greater than the capacity
    # try the next gem
    if (weights[m-1] > capacity):  
        return knapsack(weights, values, capacity, m-1, count)  

    # Return the maximum value that results from either choosing the gem
    # or not choosing the gem.
    return max(values[m-1] + knapsack(weights, values, capacity-weights[m-1], m-1, count+1),
               knapsack(weights, values, capacity, m-1, count)

答案 3 :(得分:0)

你可以用递归方式或迭代方式解决这个背包问题,下面是一个使用memoizatoin的递归自下而上方法,我认为这是解决这个问题的最佳方法。

# w is weights list, v is values list, aw is the total available weight
# i is the number of items (last index of the list)
# m is a dictionary for memoization

def knapsack(w, v, aw, i, m):
    try:
        return m[(i, aw)]
    except KeyError:
        if i == 0:
            if w[i] > aw:
                m[(i, aw)] = 0
                return 0
            else:
                m[(i, aw)] = v[i]
                return v[i]
        without = knapsack(w, v, aw, i-1, m)
        if (w[i] > aw):
            m[(i, aw)] = without 
            return without
        else:
            withi = v[i] + knapsack(w, v, aw-w[i], i-1, m)
            result = withi if withi > without else without
            m[(i, aw)] = result
            return result