公司的服务器上,每天会有大量的任务在队列中等待调度每个任务a执行需要消耗一定的资源量resource[a]调度的过程中有下列要求:
- 每一天可以同时并行调度多项任务,但是每天最少需要调度一项任务,每个任务的完成时间是一天
- 第k天调度a任务的前提:保证b任务在k-1天调度完成或者在第k天和a任务同时被调度(0<=b<a)
现在公司需要制定一个调度计划,使得在给定的天数(n)内完成所有任务的调度,并且使得总的资源消耗量最小。调度的总消耗指的是n天每一天的消耗之和,而一天的调度消耗指的是当天所有调度任务中资源量消耗最大的任务。如果n天内无法完成所有任务的调度,则输出-1
输入描述
两行输入
第1行:2个整数,调度计划的总天数n,总任务数m
第2行:一行字符串,表示各项任务调度所需要的资源量,各个任务的资源量按照空格分割
数据范围:
1≤n≤1000,1≤m≤1000
输出描述
最优调度的总消耗
示例
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
3 8
7 2 5 10 8 1 2 4
输出
15
翻译一下:
给定一个非负整数数组 nums 和一个整数 m ,将这个数组分成 m 个非空的连续子数组。
求这 m 个子数组各自最大值之和的最小值。
思路
这是一个经典的动态规划问题,可以使用动态规划来解决。下面是解决该问题的步骤:
- 首先,确定动态规划的状态。我们可以定义一个二维数组 dp,其中 dp[i][j] 表示将数组的 [0,i] 的元素分成 (j +1)个子数组时最小的子数组最大值之和。
- 初始化边界条件。当只有一个子数组时,每个子数组的最大值就是数组中的最大值。因此,我们可以将 dp[i][0] 初始化为数组[0,i] 的元素的最大值。
- 接下来,我们需要计算 dp[i][j] 的值。我们可以使用一个额外的变量存储数组区间的最大值,然后从 0 开始遍历到i-1(变量k),将数组分成两部分。在计算 dp[i][j] 时,我们可以将数组的(k,i] 的元素作为一个子数组,将剩余的元素分成 j-1 个子数组。这样,dp[i][j] 的值就可以通过 dp[k][j-1] 和区间(k,i]的最大值来计算。
- dp[taskNum - 1][dayNum - 1] 即为所求的结果。
题解如下:
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int dayNum = scanner.nextInt();
int taskNum = scanner.nextInt();
int[] resources = new int[taskNum];
for (int i = 0; i < taskNum; i++) {
resources[i] = scanner.nextInt();
}
int solution = new Solution().solution(dayNum, taskNum, resources);
System.out.println(solution);
}
int solution(int dayNum, int taskNum, int[] resources) {
if (dayNum > taskNum) {
return -1;
}
// dp[i][j]表示[0,i]的任务被分配到j天
int[][] dp = new int[taskNum][dayNum];
for (int i = 0; i < taskNum; i++) {
for (int j = 0; j < dayNum; j++) {
dp[i][j] = Integer.MAX_VALUE/2;
}
}
// maxV[i][j]表示区间[i,j]中的最大值
int[][] maxV = new int[taskNum][taskNum];
for (int i = 0; i < taskNum; i++) {
for (int j = i; j < taskNum; j++) {
if (i == 0 && j == 0)
maxV[i][j] = resources[0];
else
maxV[i][j] = Math.max(resources[j], maxV[i][j - 1]);
}
}
for (int i = 0; i < taskNum; i++) {
// 将[0,i]划分为(j+1)部分
for (int j = 0; j < i + 1 && j < dayNum; j++) {
if (j == 0) {
dp[i][j] = maxV[0][i];
continue;
}
for (int k = j - 1; k < i; k++) {
dp[i][j] = Math.min(dp[i][j], dp[k][j - 1] + maxV[k + 1][i]);
}
}
}
return dp[taskNum - 1][dayNum - 1];
}
}