做题笔记:小S的货船租赁冒险| 豆包MarsCode AI 刷题

39 阅读3分钟

问题描述

小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本 v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。

  • Q: 货船的种类数量。
  • V: 李华可用的总预算(单位:元)。
  • ships: 一个列表,其中每个元素是一个元组 [m[i], v[i], w[i]],分别表示第 i 种货船的数量、租赁价格和每艘货船的最大载货量。

测试样例

  • 样例1

    输入:Q = 2,V = 10,ships = [[2, 3, 2], [3, 2, 10]]
    输出:32

  • 样例2

    输入:Q = 3,V = 50,ships = [[5, 10, 20], [2, 20, 30], [3, 15, 25]]
    输出:100

  • 样例3

    输入:Q = 1,V = 100,ships = [[10, 5, 50]]
    输出:500

  • 样例4

    输入:Q = 4,V = 100,ships = [[1, 100, 200], [2, 50, 100], [3, 33, 66], [4, 25, 50]]
    输出:200

  • 样例5

    输入:Q = 2,V = 300,ships = [[100, 1, 1], [50, 5, 10]]
    输出:550

解题思路

  • 明确问题为背包问题
  • 该题中由于货船有多只,所以为多重背包问题。但多重背包问题本质为01背包问题,具体作法为将每种船只摊开
  • 建立二维dp[i][j]数组,表示从摊开后下标为[0-i]的船只里任意取,满足最大花费小于等于j的租赁价格下,最大载货重量为多少

代码实现

第一步

将每种船只摊开。cost代表每个船只的租赁花费,value代表每个船只的载货量。这一步就相当于将多重背包问题转换为01背包。

cost, value := []int{}, []int{}
for i := 0; i < Q; i++ {
    for j := 0; j < ships[i][0]; j++ {
       cost = append(cost, ships[i][1])
       value = append(value, ships[i][2])
    }
}

第二步

初始化dp数组,由于dp[i][j]源于上一层dp[i-1][0~j]。当i为0时就需要初始化。具体为,当j<cost[0]时,dp[0][j]应该是0,因为此时不足以租赁船只。当j>=cost[0]时,dp[0][j]应该是value[0],因为此时金额可以租赁船只0。

dp := make([][]int, len(cost))
for i := range dp {
    dp[i] = make([]int, V+1)
}
for i := cost[0]; i <= V; i++ {
    dp[0][i] = value[0]
}

第三步

开始遍历所有船只,以及金额。此时金额与船的租赁该船的租赁价格价格会有两种关系。第一种j < cost[i],即金额小于该船的租赁价格,此时dp[i][j] = dp[i-1][j]。第二种,j >= cost[i],即金额大于该船的租赁价格,此时可以从租赁或者不租赁选择较大的一个。bigger(dp[i-1][j], dp[i-1][j-cost[i]]+value[i])。

for i := 1; i < len(cost); i++ {
    for j := 0; j <= V; j++ {
       if j < cost[i] {
          dp[i][j] = dp[i-1][j]
       } else {
          dp[i][j] = bigger(dp[i-1][j], dp[i-1][j-cost[i]]+value[i])
       }
    }
}

第四步

返回结果

return dp[len(cost)-1][V]