问题描述
小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
解题思路
问题概要
小S希望在预算范围内,租用货船来最大化其总载货量。这是一个多重背包问题的变种,其中:
- 每种货船类型有一个固定数量限制(类似于有限物品数量)。
- 每艘货船有固定租赁成本和对应的载货量。
目标是找到在总预算 V 内,货船组合的最大载货量。
问题分析
这是一个非常经典的动态规划背包问题,可以直接把它作为模板题看待。采用最常规的解法:
-
状态定义: 定义一个数组
dp[Q][V],表示在预算 V 下租用 Q 艘船,能够租用的最大总载货量。 -
状态转移方程: 对于每种货船类型,如果选择租用第 i 类货船,则有:
- 当租用 k 艘第 i 类货船时,有 0 < k < m[i] 且 k*v[i]<当前剩余的预算j。
- 需消耗预算 k⋅v[i],获得载货量 k⋅w[i]。
对应的转移公式为:
-
初始条件: dp[0][0]=0,即在预算为 0 ,不租用任何一艘船时,载货量为 0。
-
最终结果: 计算并输出 dp[Q][V],即在预算 V 内租用 Q 艘船的最大总载货量。
解题步骤
- 输入处理:读取 Q、V、货船数组 ships。
- 初始化:构建 DP 数组
dp[Q][V]并初始化。 - 状态转移:逐种货船类型处理,根据多重背包逻辑更新
dp。 - 输出结果:输出 dp[Q][V]。
总结
通过动态规划和多重背包的优化,不断更新背包的最大利用率,从而达到解题的目的,也保证时间和空间效率。
代码展示
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int Q, int V, List<List<Integer>> ships) {
int[][] dp = new int[Q + 1][V + 1];
for (int i = 1; i <= Q; i++) {
List<Integer> ship = ships.get(i - 1);
int num = ship.get(0);
int value = ship.get(1);
int weight = ship.get(2);
for (int j = 1; j <= V; j++) {
for (int k = 0; k <= num && k * value <= j; k++) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * value] + k * weight);
}
}
}
return dp[Q][V];
}
public static void main(String[] args) {
// You can add more test cases here
List<List<Integer>> ships = new ArrayList<>();
ships.add(List.of(2, 3, 2));
ships.add(List.of(3, 2, 10));
List<List<Integer>> ships2 = new ArrayList<>();
ships2.add(List.of(30, 141, 47));
ships2.add(List.of(9, 258, 12));
ships2.add(List.of(81, 149, 13));
ships2.add(List.of(91, 236, 6));
ships2.add(List.of(27, 163, 74));
ships2.add(List.of(34, 13, 58));
ships2.add(List.of(61, 162, 1));
ships2.add(List.of(80, 238, 29));
ships2.add(List.of(36, 264, 28));
ships2.add(List.of(36, 250, 2));
ships2.add(List.of(70, 214, 31));
ships2.add(List.of(39, 116, 39));
ships2.add(List.of(83, 287, 4));
ships2.add(List.of(61, 269, 94));
ships2.add(List.of(23, 187, 46));
ships2.add(List.of(78, 33, 29));
ships2.add(List.of(46, 151, 2));
ships2.add(List.of(71, 249, 1));
ships2.add(List.of(67, 76, 85));
ships2.add(List.of(72, 239, 17));
ships2.add(List.of(61, 256, 49));
ships2.add(List.of(48, 216, 73));
ships2.add(List.of(39, 49, 74));
System.out.println(solution(2, 10, ships) == 32);
System.out.println(solution(23, 400, ships2) == 1740);
}
}