题目大意: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]小的永远更好。
原来是这样用的 😉