【问题标题】:Knapsack variation背包变体
【发布时间】:2018-12-16 20:19:30
【问题描述】:

所以我有一系列优惠券,每张都有价格和可以从中购买的物品数量。我只能从优惠券中购买给定的商品数量,不能多也不能少。如何找到获得所需数量的带有优惠券的商品的最低成本(如果不可能,则返回 -1)?

例如,如果有 4 张优惠券:“10 美元买 3”、“4 美元买 2”、“4 美元买 2”和“3 美元买 1”,并且要购买 4 件商品,则最低成本是 8 美元。

背包致力于寻找最大值,但对于最小值,它会继续不考虑任何优惠券并得出0的答案。

这是我的代码:

int minimumCost(coupon_t coupons[], int numCoupons, int units) {

    if (units <= 0 || numCoupons <= 0)
        return 0;

    if (coupons[numCoupons-1].quantity > units)
        return minimumCost(coupons, numCoupons-1, units);

    coupon_t coupon = coupons[numCoupons-1];
    return min(coupon.price + minimumCost(coupons, numCoupons-1, units-coupon.quantity),
            minimumCost(coupons, numCoupons-1, units));

}

【问题讨论】:

    标签: recursion dynamic-programming knapsack-problem


    【解决方案1】:

    对此进行了更多思考。正如您所说,关键是处理0。在典型的背包代码中,0 有两种含义:“不买”和“买不到”。拆分这些似乎有效:

    def minimum_cost(coupons, units, coupon_no=0):
        if units < 0 or coupon_no == len(coupons):
            # special value for "impossible"
            return None
    
        if units == 0:
            # no more space, so we're not buying anything else
            return 0
    
        quantity, price = coupons[coupon_no]
        next_coupon = coupon_no + 1
    
        if quantity > units:
            return minimum_cost(coupons, units, next_coupon)
    
        pre_purchase_value_when_used = minimum_cost(coupons, units - quantity, next_coupon)
        value_when_unused = minimum_cost(coupons, units, next_coupon)
    
        # return whichever is not impossible, or cheaper of two possibilities:
        if pre_purchase_value_when_used is None:
            return value_when_unused
        elif value_when_unused is None:
            return pre_purchase_value_when_used + price
        else:
            return min(pre_purchase_value_when_used + price, value_when_unused)
    
    coupons = [[3, 10], [2, 4], [2, 4], [1, 3]]
    units = 4
    cost = minimum_cost(coupons, units)
    print(cost)
    # => 8
    

    (注意不是,除非你缓存函数结果,虽然让它使用表格应该不会太难。关于动态编程的关键见解是使用存储来避免重新计算我们已经计算过的东西。)

    【讨论】:

    • 好吧,这似乎可行。我会记住你所说的,谢谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2018-01-31
    • 2014-01-06
    相关资源
    最近更新 更多