请帮助我解决分数背包问题(战利品的最大值)
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()
【讨论】:
感谢您的帮助以上是关于请帮助我解决分数背包问题(战利品的最大值)的主要内容,如果未能解决你的问题,请参考以下文章