历经不足两天,接近两天,哥终于 A 了你!
题意 : 假设有M本书(编号为1,2,…,M),想将每本复制一份,M本书的页数可能不同(分别是a1,a2,…,aM)。
任务时将这M本书分给K 个抄写员(K≤M〉,每本书只能分配给一个抄写员进行复制,而每个抄写员所分配到的书必须是连续顺序的。
要求复制总时间最短, 该如何分配抄写。
用 DP 做的,DP 还算不难,后续的处理挺繁琐。对于我等水平来说,不容易 !
// 方程 : dp[i][j] = min(dp[i][j], max(dp[i-1][v], sum[j]-sum[v])) i 个人 抄写 前j 本书 --> 数据 : 2 7 3 3 5 输出 :2 7 / 3 / 3 5
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
using namespace std;
const int N = 510;
const int INF = 0x7fffffff;
int dp[N][N]; // 方程 : dp[i][j] = min(dp[i][j], max(dp[i-1][v], sum[j]-sum[v])) i 个人 抄写 前j 本书
int sum[N];
int a[N];
int path[N];
int main() {
int T, m, k, i, j, v;// tmp;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &m, &k);
for(i = 0; i <= k; i++) {
for(j = 0; j <= m; j++) {
dp[i][j] = INF;
}
}
memset(sum, 0, sizeof(sum));
for(i = 1; i <= m; i++) { /// 书的页数
scanf("%d", &a[i]);
sum[i] += (sum[i-1] + a[i]);
dp[1][i] = sum[i];
}
for(i = 2; i <= k; i++) {
for(j = i; j <= m; j++) {
for(v = i-1; v <= j; v++) {
dp[i][j] = min(dp[i][j], max(dp[i-1][v], sum[j]-sum[v]));
}
}
}
int ans = dp[k][m];
int t_sum = 0;
for(i = m, j = k-1; i >= 1; i--){
t_sum += a[i];
if(t_sum > ans || i <= j){
path[j--] = i+1; // 3 4 5
t_sum = a[i];
}
}
for(i=j=1; i <= m; i++){
if(i > 1) printf(" ");
if(j < k && path[j] == i){
printf("/ ");
j++;
}
printf("%d", a[i]);
}
printf("\n");
}
system("pause");
return 0;
}