请帮助我解决分数背包问题(战利品的最大值)

Posted

技术标签:

【中文标题】请帮助我解决分数背包问题(战利品的最大值)【英文标题】:Please help me in solving Fractional Knapsack problem (Maximum Value of the Loot) 【发布时间】:2020-05-09 19:43:45 【问题描述】:

战利品的最大值

问题介绍: 小偷发现的战利品比他的包装得下要多得多。假设战利品的任何一部分都可以放入他的包中,帮助他找到最有价值的物品组合。 问题描述任务:此代码问题的目标是实现分数背包问题的算法。 输入格式:输入的第一行包含数字????物品数量和容量???的背包。下一个 ????行定义项目的值和重量。 ????-th 行包含整数?????????和???????? - 分别是第 ???? 项的价值和重量。 约束:1≤????≤103,0≤???? ≤2·106;0≤?????????? ≤2·106,0????????? ≤2·106 for all 1≤????≤??????。所有数字都是整数。 输出格式 输出适合背包的物品分数的最大值。你程序的答案与最优值之差的绝对值最多应该是 -3 您的答案虽然计算正确,但由于四舍五入问题可能会被证明是错误的)。

示例 1。

输入: 3 50 60 20 100 50 120 30 输出: 180.0000 为了达到 180 的价值,我们将第一项和第三项放入包中。

示例 2。

输入: 1 10 500 30 输出: 166.6667

我的代码:

# Maximum Value of the Loot

def knapsack(n, capacity, value_list, weight_list):
    unitValues_list = []
    
    #First lets calculate the unitValues_list
    for i in range (n):
        unitValue = (value_list[i]/weight_list[i])
        unitValues_list.append(unitValue)
    
    #Now lets fill the knapsack, intake is how much is in the bag at the moment!
    intake = 0
    max_value = 0
    factor = True

    while(factor):
        max_index = unitValues_list.index(max(unitValues_list, default=0)) 
        # this gives the index of the max valued element
        
        if(weight_list[max_index] <= capacity):
            # In this case, full item is taken in
            intake = weight_list[max_index]
            capacity -= weight_list[max_index]
            max_value += value_list[max_index]
            
        else:
            # weight_list[max_index] > capacity
            # In this case, fraction to be taken
            intake += capacity
            capacity = 0
            max_value += unitValues_list[max_index]*intake
            
        weight_list.pop(max_index)
        value_list.pop(max_index)
        unitValues_list.pop(max_index)
        print(weight_list)

        n -= 1 #no. of items left
        factor = ((n != 0) if ((capacity != 0) if True else False) else False)

    return max_value

if __name__ == "__main__":
    value_list = []
    weight_list = []
    
    #The first line of the input contains the number ???? of items and the capacity ???? of a knapsack. 
    #The next ???? lines define the values and weights of the items. 
    
    n , capacity = map(int, input().split())
    
    for i in range (n):
        value , weight = map(int, input().split())
        value_list.append(value)
        weight_list.append(weight)
        
    #Output the maximal value of fractions of items that fit into the knapsack.
    print(":.10f".format(knapsack(n, capacity, value_list, weight_list)))

我不断收到错误消息:

失败案例 #6/13:错误答案 得到:8740.3008948546 预期:7777.731 (使用时间:0.00/5.00,使用内存:9191424/671088640。)

【问题讨论】:

【参考方案1】:

纠正错误答案

改正分数

intake += capacity
capacity = 0
max_value += unitValues_list[max_index]*intake

fraction = capacity / weight_list[max_index] 
max_value += value_list[max_index]*fraction
capacity = 0 

重构代码

def knapsack(n, capacity, value_list, weight_list):
    unitValues_list = []

    #First lets calculate the unitValues_list
    for i in range (n):
        unitValue = (value_list[i]/weight_list[i])
        unitValues_list.append(unitValue)

    #Now lets fill the knapsack, intake is how much is in the bag at the moment!
    intake = 0
    max_value = 0
    factor = True

    while(factor):
        max_index = unitValues_list.index(max(unitValues_list, default=0)) 
        # this gives the index of the max valued element

        if(weight_list[max_index] <= capacity):
            # In this case, full item is taken in
            intake = weight_list[max_index]
            capacity -= weight_list[max_index]
            max_value += value_list[max_index]

        else:
            # weight_list[max_index] > capacity
            # In this case, fraction to be taken
            fraction = capacity / weight_list[max_index] 
            max_value += value_list[max_index]*fraction
            capacity = int(capacity - (weight_list[max_index] * fraction))

        weight_list.pop(max_index)
        value_list.pop(max_index)
        unitValues_list.pop(max_index)
        print(weight_list)

        n -= 1 #no. of items left
        factor = ((n != 0) if ((capacity != 0) if True else False) else False)

    return max_value

if __name__ == "__main__":
    value_list = []
    weight_list = []

    #The first line of the input contains the number ? of items and the capacity ? of a knapsack. 
    #The next ? lines define the values and weights of the items. 

    n , capacity = map(int, input('n, capacity: ').split())

    for i in range (n):
        value , weight = map(int, input('value, weight: ').split())
        value_list.append(value)
        weight_list.append(weight)

    #Output the maximal value of fractions of items that fit into the knapsack.
    print(":.10f".format(knapsack(n, capacity, value_list, weight_list)))

注意

没有提到时间问题。

通过对unitValues_list进行排序而不是每次都计算最大值,可以将复杂度从当前的O(n^2)算法更改为O(n*log(n))。

【讨论】:

@DelFerns——没问题。希望它有所帮助。 @DelFerns-- 如果我的回答有帮助,请不要忘记what to do when someone answers my questions【参考方案2】:

这是战利品问题的解决方案。按照贪心算法,我们从单价最高的商品开始填充..

def loot(t_weight,cost, unit,weight):
    count = 0
    while t_weight!=0:
        c_cost = max(unit)
        act_ind = unit.index(c_cost)
        c_weight=weight[act_ind]
        print(c_cost,c_weight,act_ind)
        if c_weight >= t_weight:
            count+=t_weight*c_cost
            t_weight = 0
        elif c_weight<t_weight:
            t_weight-=c_weight
            count+=(c_weight)*c_cost
            cost.pop(act_ind)
            unit.pop(act_ind)
            weight.pop(act_ind)
            print()
    return count
    
    
def main():
    g1=str(input())
    item,cap = map(int,g1.split())
    dict=
    cost=[]
    weight=[]
    unit =[]
    for i in range(1,item+1):
        g2=str(input())
        a,b = map(int,g2.split())
        cost.append(a)
        weight.append(b)
        j = (cost[i-1])/weight[i-1]
        unit.append(j)
    print(loot(cap,cost,unit,weight))
main()

【讨论】:

感谢您的帮助

以上是关于请帮助我解决分数背包问题(战利品的最大值)的主要内容,如果未能解决你的问题,请参考以下文章

用动态规划求解分数背包问题

编程竞赛中的背包变体

python 贪心算法解决分数背包问题

C#分数背包o(n logn)解

P4322 [JSOI2016]最佳团体(分数规划&树上背包)

bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)