[bzoj2726][DP]任务安排

本文介绍了一种通过动态规划和斜率优化解决任务分组问题的方法,旨在寻找最优分组方案以最小化总费用。

Description

机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1,2,3…N。这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和。注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数Ci。请确定一个分组方案,使得总费用最小。

Input

第一行两个整数,N,S。 接下来N行每行两个整数,Ti,Ci。

Output

一个整数,为所求的答案。

Sample Input

5 1

1 3

3 2

4 3

2 3

1 4

Sample Output

153

题解

设t[i]表示t的前缀和 c[i]表示f的前缀和
首先dp方程给出
f[i]=min(f[j]+t[i](c[i]c[j])+S(c[n]c[j]))f[i]=min(f[j]+t[i]∗(c[i]−c[j])+S∗(c[n]−c[j]))
此处影响释放给了后面的任务
大力斜率优化,可以发现在j<kj<k

f[j]f[k]c[j]c[k]<t[i]+Sf[j]−f[k]c[j]−c[k]<t[i]+S

k比j优秀
于是维护一个下凸壳
观察到t[i]没有单调性,不能直接单调队列
我们二分出第一个左边线段斜率小于S+t[i]S+t[i],右边线段斜率大于S+t[i]S+t[i]的点
这个点就是最佳决策点
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL f[310000],c[310000],t[310000],S;
int n;
double slop(int j,int k){return (double)(f[j]-f[k])/(c[j]-c[k]);}
int li[310000],head,tail;
int fdans(LL gg)
{
    int l=head,r=tail;
    while(l<r)
    {
        int mid=(l+r)/2;
        if((f[li[mid]]-f[li[mid+1]])>gg*(c[li[mid]]-c[li[mid+1]]))l=mid+1;
    //    if(slop(li[mid],li[mid+1])<gg)l=mid+1;
        else r=mid;
    }
    return li[l];
}
int main()
{
//  freopen("a.in","r",stdin);
//  freopen("a.out","w",stdout);
    scanf("%d%lld",&n,&S);
    for(int i=1;i<=n;i++)scanf("%lld%lld",&t[i],&c[i]),t[i]+=t[i-1],c[i]+=c[i-1];
    f[0]=0;
    li[1]=0;head=tail=1;
    for(int i=1;i<=n;i++)
    {
        int p=fdans(t[i]+S);
        f[i]=f[p]+t[i]*(c[i]-c[p])+S*(c[n]-c[p]);
        while(head<tail && (f[li[tail-1]]-f[li[tail]])*(c[i]-c[li[tail]])<=(f[i]-f[li[tail]])*(c[li[tail-1]]-c[li[tail]]))tail--;
        li[++tail]=i;
    }
    printf("%lld\n",f[n]);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值