当前位置:首页 > 动态规划 > 斜率优化 > 正文
SSOJ2888任务安排123
637+

题目大意:n个任务分成若干批依次完成,每个批次启动时间为S,每个任务耗时为$T_i$,费用为该批次完成时间乘以$C_i$,总费用最小是多少?

【题目描述】

有 $N$ 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。机器会把这 $N$ 个任务分成若干批,每一批包含连续的若干个任务。从时刻 $0$ 开始,任务被分批加工,执行第i个任务所需的时间是 $T_i$。另外,在每批任务开始前,机器需要 $S$ 的启动时间,故执行一批任务所需的时间是启动时间 $S$ 加上每个任务所需时间之和。

一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。也就是说,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数 $C_i$ 。

请为机器规划一个分组方案,使得总费用最小。

【输入】

第一行两个整数,分别为 $N,S$;

接下来 $N$ 行每行两个整数 $T_i,C_i$ 。

【输出】

一个数,最小的总费用。

【输入样例】

5 1
1 3
3 2
4 3
2 3
1 4

【输出样例】

153

【提示】

数据范围与提示:对于全部数据,$1\le N\le 3 × 10^5,1\le S\le 2^8,|T_i|\le 2^8,0\le C_i\le 2^8$。

解题思路

对于数据范围不超过5000,我们可以得到状态转移方程:f[i] = f[j] + (t[i]+ci*S) * (c[i]-c[j])

这样还需要增加一位状态记录转移次数、枚举转移次数ci。

我们可以运用”费用提前计算的思想”,既然后面都需要耗费启动时间,我们可以先计算,这样后面就不需要管之前的次数了。

转移方程为:f[i] = f[j] + t[i]*(c[i]-c[j]) + S*(c[n]-c[j]),后面的所有任务都需要乘以启动时间S,那就先乘了。

程序实现

暴力枚举最后一个分组的情况,按照转移方程计算即可。

公式展开后,将完全未知的、只含j的项放右边,将既含有i又含有j的项放左边,可得:f[i] + t[i]*c[j] = f[j]-S*c[j] + t[i]*c[i] + S*c[n]

其中未知量有c[j]和f[j]-S*c[j],带常数的是x,不带常数的是y,斜率k = t[i]。

只含有i的是常数,为了另f[i]最小,我们希望截距最小,对于之前的两个点j1和j2,其中j1 < j2。

如果j1和j2的斜率大于k,那么选择j1截距更小;否则效率小于k选择j2更好。

由于斜率t[i]不递减,所以保留斜率大的,因为遇到斜率小的,j2更好,j1永远不会比j2好。

最后考虑维护斜率递增还是递减:j1 < j2 < j3,如果转折点最好,必然j1和j2斜率小于k,j2和j3斜率大于k,斜率递减中间点不可能是最优决策。

因此,维护斜率大于k,且斜率单调递增。

对于斜率k不递增的情况,可能出现斜率暂时小于k的,后面也有可能大于新的k,让j1成为最优决策,j1和j2都需要保留下来。

但是斜率还是跟之前一样,需要维护递增,这样,最优决策在最后一个斜率小于k的位置、第一个大于k的位置,可以二分查找。

注意:斜率不存在,需要特殊处理一下。

本题中,斜率不存在,费用系数为0,前缀和c[i]是相等的,转移方程是f[i] = f[j] + t[i]*(c[i]-c[j]) + S*(c[n]-c[j]),f[j]小的永远更好。

报歉!评论已关闭.