任务安排1
题目传送门
一个重要思想:当前的 \(s\) 准备时间对之后的影响可以用后面所有的和 \(\times s\)。利用上述性质,可以提前计算每个分组中 \(s\) 的贡献,消除后效性。\(f[i]\) 表示以 \(i\) 为一段的末尾的答案。由此可以得出方程是 \(f[i]=\min f[j]+(sumc[i]-sumc[j])*sumt[i]+(sumc[n]-sumc[j])*s\),其中 \(j\) 表示以 \(j\) 结尾为一组,\(j+1\sim i\) 为一组。这个方程已经可以用 \(O(n^2)\) 的时间复杂度解决问题了。
#include<bits/stdc++.h>
using namespace std;
#define L(i,l,r) for(int i=l;i<=r;++i)
#define R(i,l,r) for(int i=r;i>=l;--i)
typedef long long ll;
const int N=5010;
int n,s,sumc[N],sumt[N];
ll f[N];
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
scanf("%d%d",&n,&s);
L(i, 1, n){
int a,b;
scanf("%d%d",&a,&b);
sumt[i]=sumt[i-1]+a;
sumc[i]=sumc[i-1]+b;
}
memset(f+1,0x3f,n*8);
L(i, 1, n)
L(j, 0, i-1)f[i]=min(f[i],f[j]+1ll*(sumc[i]-sumc[j])*sumt[i]+(sumc[n]-sumc[j])*s);
printf("%lld",f[n]);
return 0;
}