题解【CJOJ1371】[IOI2002]任务安排

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



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 }
原文地址:https://www.cnblogs.com/xsl19/p/10461721.html