题目分析
需要在预算 V 内,选择不同类型的货船,使得总载货量最大化。每种货船有数量限制,租赁成本和载货量。
- 初始化 dp 数组:
dp[i][j]表示在前i种货船中,预算为j时的最大载货量。 - 遍历每种货船:对于每种货船,考虑选择0到
m[i]艘货船的情况。 - 更新 dp 数组:在每种预算下,更新
dp数组,考虑选择不同数量的货船。
解题思路
- 初始化
dp数组,dp[0][j] = 0表示没有货船时,无论预算多少,载货量都是0。 - 对于每种货船,考虑选择0到
m[i]艘货船的情况,更新dp数组。 - 最终答案就是
dp[Q][V],即在前Q种货船中,预算为V时的最大载货量。
java代码
public class Main {
public static int solution(int Q, int V, List<List<Integer>> ships) {
// 初始化dp数组,dp[i][j]表示在前i种货船中,预算为j时的最大载货量
int[][] dp = new int[Q + 1][V + 1];
// 遍历每种货船
for (int i = 1; i <= Q; i++) {
int m = ships.get(i - 1).get(0); // 货船数量
int v = ships.get(i - 1).get(1); // 租赁成本
int w = ships.get(i - 1).get(2); // 载货量
// 遍历预算
for (int j = V; j >= 0; j--) {
// 考虑选择0到m艘货船的情况
for (int k = 0; k <= m && k * v <= j; k++) {
// 更新dp数组
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v] + k * w);
}
}
}
// 返回最大载货量
return dp[Q][V];
}
public static void main(String[] args) {
// 测试用例
List<List<Integer>> ships = new ArrayList<>();
ships.add(List.of(2, 3, 2));
ships.add(List.of(3, 2, 10));
System.out.println(solution(2, 10, ships) == 32);
}
}
动态规划思想
这种解决问题的方式很好地体现了动态规划的思想,通过将大问题分解为子问题,并利用子问题的解来构建大问题的解。通过逐步考虑每种货船的选择情况,在不同的预算限制下计算最大载货量,最后得到整体的最优解。
-
时间复杂度
- 有三层嵌套的循环。外层循环遍历
Q种货船,中层循环遍历预算V,内层循环最多遍历m艘货船。所以总的时间复杂度是𝑂(𝑄∗𝑉∗𝑚)O(Q∗V∗m)。
- 有三层嵌套的循环。外层循环遍历
-
空间复杂度
- 创建了一个大小为
(Q + 1) * (V + 1)的二维数组dp来存储中间结果。如果Q和V的值很大,可能会占用较多的内存空间。考虑优化空间复杂度,例如使用滚动数组来减少空间占用,因为在计算dp[i][j]时,只需要用到dp[i - 1][*]的值,可以通过复用数组空间来优化。
- 创建了一个大小为