1、任务安排 I
由于每次的启动消耗的时间会对后面的所有任务都产生影响,所以在进行当前组任务时先将启动产生的影响累加到当前组别中,方便于计算后面的状态。
集合
f [ i ] f[i] f[i]:表示将前 i i i 个任务分批执行的最小费用
集合划分
以 i i i 结尾的该批次任务的开头进行划分。上面一个批次结尾为 j ∈ [ 0 , i − 1 ] j \in[0,i-1] j∈[0,i−1],从 j + 1 i j+1~i j+1 i 是最后一批次,那么从 j + 1 j + 1 j+1 到 i i i 这一批次的消耗 = 到 i i i 的总时间 x 从 j j j 到 i i i 的 费用之和 + 最后一批任务启动时间对当前任务及后续任务整体的影响。即 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 ] ) Sumt[i] \times (Sumc[i] - Sumc[j]) + S * (Sumc[n] - Sumc[j]) Sumt[i]×(Sumc[i]−Sumc[j])+S∗(Sumc[n]−Sumc[j])最终的状态转移方程为: 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] \times (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]))
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 5010;
int n, s;
int sc[N], st[N];
LL f[N];
int main() {
scanf("%d%d", &n, &s);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &st[i], &sc[i]);
st[i] += st[i - 1];
sc[i] += sc[i - 1];
}
memset(f, 0x3f, sizeof f);
f[0] = 0; // 处理前0个任务的花费 = 0
for (int i = 1; i <= n; i++)
for (int j = 0; j < i; j++)
f[i] = min(f[i], f[j] + (sc[i] - sc[j]) * (LL) st[i] + (LL) s * (sc[n] - sc[j]));
printf("%lld\n", f[n]);
return 0;
}
2、任务安排 II(凸包优化)
由上一题的公式可得如下推导(这里暂时不考虑 m i n min min):
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 ( j ) − ( S + S u m t [ i ] ) × S u m c [ j ] + S u m t [ i ] × S u m c [ i ] + S × S u m c [ n ] \begin{aligned} f(i)&=f(j)+Sumt[i] \times (Sumc[i] - Sumc[j]) + S \times (Sumc[n]-Sumc[j])\\ &= f(j)-(S+ Sumt[i]) \times Sumc[j]+ Sumt[i] \times Sumc[i] + S \times Sumc[n]\\ \end{aligned} f(i)=f(j)+Sumt[i]×(Sumc[i]−Sumc[j])+S×(Sumc[n]−Sumc[j])=f(j)−(S+Sumt[i])×Sumc[j]+Sumt[i]×Sumc[i]+S×Sumc[n]经过进一步变形有
f ( j ) = ( S u m t [ i ] + S ) × S u m c [ j ] + f ( i ) − S u m t [ i ] × S u m c [ i ] − S × S u m c [ n ] f(j)=(Sumt[i]+S) \times Sumc[j]+f(i)-Sumt[i] \times Sumc[i] - S \times Sumc[n] f(j)=(Sumt[i]+S)×Sumc[j]+f(i)−Sumt[i]×Sumc[i]−S×Sumc[n]这里我们令
y = f ( j ) k = S u m t [ i ] + S x = S u m c [ j ] b = f ( i ) − S u m t [ i ] × S u m c [ i ] − S × S u m c [ n ] \begin{aligned} y &= f(j)\\ k &= Sumt[i] + S\\ x &= Sumc[j]\\ b &= f(i)-Sumt[i] \times Sumc[i] - S \times Sumc[n] \end{aligned} ykxb=f(j)=Sumt[i]+S=Sumc[j]=f(i)−Sumt[i]×Sumc[i]−S×Sumc[n]因此整个式子可以表示成 y = k x + b y = kx+b y=kx+b又因为 j ∈ [ 0 ,