任务安排1 斜率优化DP
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了任务安排1 斜率优化DP相关的知识,希望对你有一定的参考价值。
题目:
有 N 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。
机器会把这 N 个任务分成若干批,每一批包含连续的若干个任务。
从时刻 0 开始,任务被分批加工,执行第 i 个任务所需的时间是 Ti。
另外,在每批任务开始前,机器需要 S 的启动时间,故执行一批任务所需的时间是启动时间 S 加上每个任务所需时间之和。
一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。
也就是说,同一批任务将在同一时刻完成。
每个任务的费用是它的完成时刻乘以一个费用系数 Ci。
请为机器规划一个分组方案,使得总费用最小。
1
≤
N
≤
5000
1≤N≤5000
1≤N≤5000
0
≤
S
≤
50
0≤S≤50
0≤S≤50
1
≤
T
i
,
C
i
≤
100
1≤Ti,Ci≤100
1≤Ti,Ci≤100
思路:
状态表示:
f
[
i
]
f[i]
f[i]表示从前i
个里面选,所有选择方案里面的最小费用
转移方程:
f [ i ] = m i n ( f [ i ] , f [ j ] + s u m t [ i ] ∗ ( s u m c [ i ] − s u m c [ j ] ) + s ∗ ( s u m c [ n ] − s u m c [ j ] ) ) f[i] = min(f[i],f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j])) f[i]=min(f[i],f[j]+sumt[i]∗(sumc[i]−sumc[j])+s∗(sumc[n]−sumc[j]))
对任务分批相当于是对任务进行插空,插一个空就会将任务分成左右两批
j
是最后一个对任务插空的位置,区间
[
j
+
1
,
i
]
[j+1,i]
[j+1,i]则一批任务,
j
j
j是可变的,
0
≤
j
≤
i
0 \\leq j \\leq i
0≤j≤i
每个插空可以把费用插空间隔的费用提前算出来,即为
s
∗
(
s
u
m
c
[
n
]
−
s
u
m
c
[
j
]
)
)
s*(sumc[n]-sumc[j]))
s∗(sumc[n]−sumc[j])),剩下的整体的费用不变
s u m t [ i ] ∗ ( s u m c [ i ] − s u m c [ j ] ) sumt[i]*(sumc[i]-sumc[j]) sumt[i]∗(sumc[i]−sumc[j])是区间 [ i , j ] [i,j] [i,j]时间的总费用
最终的时间复杂度为 O ( n 2 ) O(n^2) O(n2)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 5005;
int n,s;
int f[N];
int sumt[N],sumc[N];
int main()
{
cin>>n>>s;
for(int i=1;i<=n;i++)
{
cin>>sumt[i]>>sumc[i];
sumt[i] += sumt[i-1];
sumc[i] += sumc[i-1];
}
memset(f,0x3f3f,sizeof f);
f[0] = 0;
for(int i=1;i<=n;i++)
for(int j=0;j<i;j++)
f[i] = min(f[i],f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j]));
cout<<f[n]<<'\\n';
return 0;
}
以上是关于任务安排1 斜率优化DP的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2726: [SDOI2012]任务安排 [斜率优化DP 二分 提前计算代价]