Problem’s Website
- 数据包的调度机制
Solution
这道题是一道区间dp,状态的设法有很多种,可以设f[i][j]为从i到j的最小延迟值,答案为f[1][n],状态转移时,我们先枚举区间长度l,再分别枚举左右端点i,j,再枚举i-j之间的点k,方程为
1
f[i][j] = min(f[i][j], f[i][k - 1] + f[k + 1][j] + a[k] * (l - 1) + (sum[j] - sum[k]) * (k - i));
要注意我们枚举的k表示最后一个出栈的是k,那么前面的出栈的顺序为k—i+1,所以我们可以用前缀和来维护。
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using namespace std;
int sc() {
int xx = 0, ff = 1; char cch = gc;
while(cch < '0' || cch > '9') {
if(cch == '-') ff = -1; cch = gc;
}
while(cch >= '0' && cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
int t, n;
int f[110][110];
int a[110], sum[110];
int main() {
t = sc();
while(t--) {
memset(sum, 0, sizeof(sum));
memset(f, 0, sizeof(f));
n = sc();
for(int i = 1; i <= n; i++)
a[i]= sc(), sum[i] = sum[i - 1] + a[i];
for(int l = 1; l <= n; l++) {
for(int i = 1; i <= n - l + 1; i++) {
int j = i + l - 1;
f[i][j] = INF;
for(int k = i; k <= j; k++)
f[i][j] = min(f[i][j], f[i][k - 1] + f[k + 1][j] + a[k] * (l - 1) + (sum[j] - sum[k]) * (k - i));
}
}
printf("%d\n", f[1][n]);
}
return 0;
}
rp++