目录
最后得分:
问题描述:
思路分析:
既然不能通过枚举所有的情况来找到答案(得分70分) ,那肯定是有一种途径来找到最优解,所以自然的联想到了dp(动态规划);我们再来看一下这个问题,寻找超过包邮条件x的最小数字组合。可以转化为先求书的总价sum,再用sum减去x得y,问题就变成了寻找不超过y(达到包邮条件)的最大数字组合,再用总价减去这个数字组合,即可得到最终答案。寻找不超过y的最大数字组合,这种类型就是典型的背包问题。
比如商品总价格:sum=20+90+60+60=230 x= 100(满100包邮) y=230-100=130 寻找在130范围内的最大商品.当然我们从开始的思路就是逆向来的,所以最后回溯算法得到的列表也是不包含题目答案的答案.
参考视频:【【Python算法实战】背包问题】 https://www.bilibili.com/video/BV1PA411J7Zh/?share_source=copy_web&vd_source=4c6131e466fadade1ed95eec9f227140
注:视频中缺少一行代码,::: maxValue[i][j]=maxValue[i-1][j] #0/1背包主要代码①
我们构造的maxValue向量:
j i | 0 | 1 | 2 | 3 | ... |
0 | 0 | 0 | 0 | 0 | 0 |
20 | |||||
60 | |||||
60 | |||||
90 |
看过视频后的代码如下:
n,x =map(int,input().split())
price = []
# dp =[0] *(n*x)
for i in range(n):
a=int(input())
price.append(a)
pre =sum(price) #计算总价钱
price.sort() #可以省略
y =[i for i in range(pre-x+1)] #从0 到 y
maxValue =[ [0 for i in range(pre -x+1)] for j in range(n+1)] #第一行为0行 第一列为0列
for i in range(1,len(price)+1): #相当于物品行
weight = price[i-1] #重量
value =price[i-1] #价值
for j in range(len(y)):
maxValue[i][j]=maxValue[i-1][j] #0/1背包主要代码①
if j >= weight: #如果背包重量大于=当前物品的重量 就相当于我们可以还以塞其他物品
maxValue[i][j] = max(maxValue[i-1][j],maxValue[i-1][j-weight]+value) #0/1背包主要代码②
#没有加i行物品的价值 , 在加入上一行物品前提下,背包重量腾出i行物品的重量+i行物品的价值
# 输出看看我们的maxValue矩阵
#print(pre - maxValue[-1][-1])
# for i in range(n+1):
# print(maxValue[i])
#回溯寻找
def huishuo(maxValue,items):
sequence=[]
#i行代表物品行 j列 代表weight
i =len(maxValue)-1
j =len(maxValue[0])-1
while i >0 and j >0 :
if maxValue[i][j] == maxValue[i-1][j]: #相等代表没有加进来这个物品
i -=1
else:
sequence.append(price[i-1]) #添加进来这个物品 因为price是从1开始 所以i-1
j =j- price[i-1]
# j 减去 这个东西的重量 (没放进去这个商品的书包的容量)
i -=1 #往上一行寻找
return list(reversed(sequence)) #因为回溯寻找 最后要将结果倒置
result= huishuo(maxValue,price)
# print(result)
#以下结果为我们真正题目要求的结果
final =[]
for i in range(len(price)):
if price[i] not in result:
final.append(price[i])
print(sum(final))