P1371 - [IOI2002]任务安排
Description
N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和(同一批任务将在同一时刻完成)。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。
例如:S=1;T={1,3,4,2,1};F={3,2,3,3,4}。如果分组方案是{1,2}、{3}、{4,5},则完成时间分别为{5,5,10,14,14},费用C={15,10,30,42,56},总费用就是153。
Input
第一行是N(1<=N<=5000)。
第二行是S(0<=S<=50)。
下面N行每行有一对数,分别为Ti和Fi,均为不大于100的正整数,表示第i个任务单独完成所需的时间是Ti及其费用系数Fi。
Output
一个数,最小的总费用。
Sample Input
5
1
1 3
3 2
4 3
2 3
1 4
Sample Output
153
Source
动态规划 ,斜率优化
Solution
考虑DP。
设t[i]为完成时间的后缀和,y[i]为所需费用的后缀和。
那么DP数组h[i]就为min(h[i],h[j]+y[i]*(t[i]-t[j]+m)),m为题中所述s。
最后输出h[1]即可。
Code
1 #include <bits/stdc++.h> 2 #define int long long 3 4 using namespace std; 5 6 inline int read() 7 { 8 int f=1,x=0; 9 char c=getchar(); 10 11 while(c<'0' || c>'9') 12 { 13 if(c=='-')f=-1; 14 c=getchar(); 15 } 16 17 while(c>='0' && c<='9') 18 { 19 x=x*10+c-'0'; 20 c=getchar(); 21 } 22 23 return f*x; 24 } 25 26 int n,m,d[5005],s[5005],t[5005],y[5005],h[5005],sum,ans; 27 28 signed main() 29 { 30 freopen("batch.in","r",stdin); 31 freopen("batch.out","w",stdout); 32 33 n=read(),m=read(); 34 35 for(register int i=1; i<=n; i++) 36 { 37 d[i]=read(),s[i]=read(); 38 } 39 40 for(register int i=n; i; i--) 41 { 42 t[i]=t[i+1]+d[i]; 43 44 y[i]=y[i+1]+s[i]; 45 } 46 47 memset(h,0x3f,sizeof(h)); 48 49 h[n+1]=0; 50 51 for(register int i=n; i; i--) 52 { 53 for(register int j=i+1; j<=n+1; j++) 54 { 55 h[i]=min(h[i],h[j]+y[i]*(t[i]-t[j]+m)); 56 } 57 } 58 59 printf("%lld",h[1]); 60 61 return 0; 62 }