解法1:动态规划
public static int solution(int n, int k, int[] data) {
// Edit your code here
// dp[i][j] => 第(i)天剩余j个补给的情况下,所需花费的最小金额。求min(dp[n][0])
int[][] dp = new int[n + 1][k];
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < k; j++) {
dp[i][j] = 99999;
}
}
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= k - 1; j++) {
// x i当天购买的补给数, x >= 0
for (int x = Math.max(j + 2 - k, 0); x <= j + 1; x++) {
dp[i][j] = Math.min(dp[i][j], x * data[i - 1] + dp[i - 1][j + 1 - x]);
}
}
}
return dp[n][0];
}
解法2:单调栈+贪心
public static int solution(int n, int k, int[] data) {
// Edit your code here
Stack<Integer> stack = new Stack<>();
int[] lessIndex = new int[n];
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && data[i] <= data[stack.peek()]) {
stack.pop();
}
lessIndex[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
int cost = 0;
int remain = 0;
int i = 0;
int buy = 0;
int days = 0;
while (i < n) {
days = lessIndex[i] - i;
if (lessIndex[i] == -1) {
buy = Math.min(k-remain, n - i - remain);
} else if (days >= k) {
buy = k-remain;
} else {
buy = Math.max(days - remain, 0);
}
cost = cost + buy * data[i];
remain = remain + buy - 1;
i++;
}
return cost;
}