华为笔试题--购物单的解题思路及python实现
题目截图:
这题可以看成一个背包问题,求满足条件下的最大值。
背包问题主要的解题思路就是将原问题分解为几个子问题,并求子问题最优解。同样这里也是这样的一个思路:
题目是要在N元的基础上,购买m件商品中价格与重要性乘积最大值的组合。假设能够买得起第m件物品,如果是主件,那么它有两种选择,买或者不买,这样的话,我们从这两种选择中选取所求值最大的一种可能性,我们不需要马上得到这两种选择的具体值是多少,只需对它们求一个max();如果是附件的话,不仅需要购买这件商品,还需要购买得起它的主件。如果还是能够购买得起的话,也是有两种选择,买或者不买,这时候处理的方法和上面情况一样。对所有的物品进行遍历就能求出最优解。
# 2019.3.20 补充:在遇到两个附件的时候,原来的代码存在问题,于是在遇到附件的时候,还要考虑上遍历过程中主件已经购买的情况,这时候只需要购买附件就可以。这时候就需要在三者(不买当前附件,购买当前附件和其对应的主件(不管有没有购买其他附件,只考虑购买当前的附件和对应的主件),在前面购买主件和其他附件的基础上再购买一个附件)之中求最大值。
话不多说,上代码:
while True:
try:
N, m = map(int, input().strip().split())
a = [[0]*(N+1) for i in range(m+1)]
goods = []
for i in range(m):
goods.append(list(map(int, input().strip().split())))
for i in range(1, m+1):
for j in range(1, N+1):
if goods[i-1][2] == 0: # 表示是主件
if goods[i-1][0]<=j: # <=j表示买的起可以有选择, 这时候有两种选择,可以买也可以不买,选择最优的方案
a[i][j] = max(a[i-1][j], a[i-1][j - goods[i-1][0]]+goods[i-1][1]*goods[i-1][0])
# a[i][j] 表示用j元钱去买i件物品的最优解(这里就是(价格和重要性乘积)最大值)
else:
if goods[i-1][0]+goods[goods[i-1][2]-1][0]<=j: # 要买附件的话,必须先买主件,所以必须有能买两件的钱
a[i][j] = max(a[i-1][j],
a[i-1][j - goods[i-1][0]]+goods[i-1][0]*goods[i-1][1], # 这一行是根据 麦麦麦麦迪 的问题进行修改的 2019.3.20
a[i-1][j-goods[i-1][0] - goods[goods[i-1][2]-1][0]]+goods[i-1][0]*goods[i-1][1]+goods[goods[i-1][2]-1][0]*goods[goods[i-1][2]-1][1])
print(max([max(row) for row in a])) # 这时候矩阵右下角并不是最大值,需要求整个矩阵的最大值
except:
break
#理解的不对,望告知,相互学习才能共同进步