问题描述
小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。
Q: 货船的种类数量。V: 小S可用的总预算(单位:元)。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
解题思路
1. 问题理解
- 你需要在给定的预算V内,选择不同类型的货船,使得载货总量最大
- 每种货船都有固定的数量,租赁成本以及最大的载货量
2. 算法思路
- 定义一个dp数组,使用动态规划来解决这个问题
- dp数组大小为dp[Q+1][V+1],dp[i][j]表示在前i种货船下在价格为j的条件下,可以装多少货物
- 整体算法实现采取三层循环的架构
- 最外层循环表示第i中货船
- 中间一层循环表示花费j元最多可以装载多少货物
- 由于我们每种货船有数量限制,所以第三层循环用来计算在j元以内,你可以购买几艘i号船
- 状态转移
- 不选择当前i号船 那么dp[i][j] = dp[i-1][j]
- 选择当前i号船,则需要从预算j中扣除当前i号船的成本,同时增加载货量,即
dp[i][j] = Math.max(dp[i-1][j-numshipmoney]+numshipheight, dp[i][j]);
- num 表示i号船的数量
- shipmoney 表示i号船的成本
- shipheight 表示i号船的载货量
代码实现
public static int solution(int Q, int V, List<List<Integer>> ships) {
// Please write your code here
//初始化dp数组,dp[i][j]表示前i搜货船在价格为j的条件下,最多可以装载多少货物
int[][] dp = new int[Q+1][V+1];
for(int i = 1 ; i <= Q; i++){
List<Integer> ship = ships.get(i-1);
int shipnum = ship.get(0);
int shipmoney = ship.get(1);
int shipheight = ship.get(2);
for(int j = 0;j<=V;j++){
//花费j元,找到最多可以装载多少货物
for(int num = 0 ;num<= shipnum;num++){
if(num * shipmoney <= j){
dp[i][j] = Math.max(dp[i-1][j-num*shipmoney]+num*shipheight, dp[i][j]);
}
}
}
}
return dp[Q][V];
}