题目解析
题目描述:
小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本 v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。
Q: 货船的种类数量。V: 李华可用的总预算(单位:元)。ships: 一个列表,其中每个元素是一个元组[m[i], v[i], w[i]],分别表示第i种货船的数量、租赁价格和每艘货船的最大载货量。
思维详解:
由题可知,小S期望使用Q类数量、租赁成本与最大载货量各不一的货船在最大成本不超过V的前提下进行租赁,并要求载货量达到最大值。由于该题的最终目的是在限定条件下求解全局最优解,因此优先使用递归。现对题目进行深入分析,可知,该题为多重背包问题,租赁成本 v[i] 为背包物品重量,最大载货量 w[i]为物品价值,预算 V 为背包最大容量。接下来我将用python解题。
代码详解: 首先初始化动态dp数组为(V+1)维全0数组;使用变量sumnum记录可租赁货船数量总和;j用于记录遍历货船种类;tempnum用于记录当前遍历到的物品相对于全部物品的位置,便于判断物品种类(为了节省题解空间复杂度,在这里没有对物品数组进行展开;如若对物品数组进行展开,该步骤可忽略);z用于记录当前遍历背包容量。最后,进行一维滚动数组遍历。代码如下所示:
def solution(Q, V, ships):
# Please write your code here
sumnum=0
tempnum=0
j=0
z=V
dp=[0]*(V+1)
for i in range(Q):
sumnum+=ships[i][0]
tempnum=ships[0][0]
for i in range(sumnum):
if(tempnum==0):
j+=1
elif((i+1)/tempnum>1):
if(j+1<Q):
tempnum+=ships[j+1][0]
j+=1
while z>=ships[j][1]:
dp[z]=max(dp[z],dp[z-ships[j][1]]+ships[j][2])
z-=1
z=V
return dp[V]
if __name__ == "__main__":
# You can add more test cases here
ships = [[2, 3, 2], [3, 2, 10]]
ships2 = [[30, 141, 47], [9, 258, 12], [81, 149, 13], [91, 236, 6], [27, 163, 74], [34, 13, 58], [61, 162, 1], [80, 238, 29], [36, 264, 28], [36, 250, 2], [70, 214, 31], [39, 116, 39], [83, 287, 4], [61, 269, 94], [23, 187, 46], [78, 33, 29], [46, 151, 2], [71, 249, 1], [67, 76, 85], [72, 239, 17], [61, 256, 49], [48, 216, 73], [39, 49, 74]]
print(solution(2, 10, ships) == 32)
print(solution(23, 400, ships2) == 1740)
知识总结
本题主要应用了动态规划中的经典背包算法(多重背包),实际上属于公式题。没有接触过动态规划算法的码友初看可能没有什么思路,这里建议可以从初始楼梯问题和斐波那契数列问题进行动规入门,随后系统学习01背包问题以及完全背包问题,值得注意的是,物品背包的遍历顺序以及内外循环问题是动规的核心,dp数组的初始化更是其中精粹,学习时一定要慎之又慎。
学习计划
豆包MarsCode AI在我的刷题过程中给了我很大的帮助,千里之行始于足下,解题第一步就是读懂题,AI助手很好的为我明晰了题目要义。并且在解题过程中,AI助手也可以为我实时分析代码逻辑与漏洞,以防编程过程中的逻辑模糊现象,大大提升了解题效率。
工具运用
这里建议其他码友在题意不明时询问豆包AI,让其进行读题,明确题意。代码编程卡顿时借助AI对现有代码进行逻辑分析,获取接下来的解题思路,可有效提升效率,但要注意AI不是万能的,不能全部照抄,要融入自己的理解,才能获得最精确的题解。同时,如果发现代码于某些样例存在问题,可询问豆包AI当前代码是否存在边界问题没有考虑到。