POJ 1180 Batch Scheduling 斜率DP

Batch Scheduling POJ - 1180

总共有 NN 个任务,编号为 1N1\sim N,将这 NN 个任务分成任意多个 batch ,每个 batch 中包含连续编号的任务,按照 batch 中最小编号的顺序进行依次处理每一批,起始时刻是 00,每个 batch 的准备时间是 SS,第 ii 个任务的处理时间为 T1T_1,系数为 FiF_i,同一个 batch 里的所有任务在同一时刻输出,也就是说,在某一个 batch 中,假如他们的起始时间是 tt,包含任务的编号是 xx+kx\sim x+k,则他们的输出时间均是 t+S+i=xx+kTit+S+\sum_{i=x}^{x+k}T_i ,最终的总花费是 第 ii 个任务的输出时间乘上系数 FiF_i 后求和,求最小总花费。

考虑斜率优化。用 dp[i]dp[i] 来表示 iNi\sim N 的最小花费,则有:

dp[i]=mini<j<N{dp[j]+(S+sumt[i]sumt[j])sumc[i]} dp[i]=\min_{i<j<N}\{dp[j]+(S+sumt[i]-sumt[j])*sumc[i]\}

其中 sumt[j]sumt[j] 为处理时间 TjT_j 的后缀和,sumc[j]sumc[j] 为系数 FiF_i 的后缀和。令 j<kj<kjj 优于 kk,则有:

dp[j]+(S+sumt[i]sumt[j])sumc[i]<dp[k]+(S+sumt[i]sumt[k])sumc[i]dp[j]dp[k]<sumc[i](sumt[j]sumt[k])dp[j]dp[k]sumt[j]sumt[k]<sumc[i] \begin{aligned} dp[j]+(S+sumt[i]-sumt[j])*sumc[i]&<dp[k]+(S+sumt[i]-sumt[k])*sumc[i]\\ dp[j]-dp[k]&<sumc[i]*(sumt[j]-sumt[k])\\ \frac{dp[j]-dp[k]}{sumt[j]-sumt[k]}&<sumc[i] \end{aligned}

yj=dp[j],xj=sumt[j],sjk=yjykxjxky_j=dp[j],x_j=sumt[j],s_{jk}=\dfrac{y_j-y_k}{x_j-x_k} ,并且对于 m<j<km<j<k,可以证明若 smj<sjks_{mj}<s_{jk} ,则 jj 必定不是最优点,可舍去,证明如下:

首先,假如 sjk<sumc[i]s_{jk}<sumc[i],则 smj<sumc[i]s_{mj}<sumc[i],因此 mmjj 优;

然后,假如 sjksumc[i]s_{jk}\ge sumc[i],则 kkjj 优。

代码如下:

#include<iostream>
#include<cstdio>
//#define WINE
#define MAXN 10100
using namespace std;
int n,S,T[MAXN],f[MAXN],st[MAXN],sf[MAXN],q[MAXN],h,t,dp[MAXN];
int up(int j,int k){
    return dp[j]-dp[k];
}
int down(int j,int k){
    return st[j]-st[k];
}
int getDP(int k,int i){
    return dp[k]+(S+st[i]-st[k])*sf[i];
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    while(scanf("%d",&n)!=EOF){
        scanf("%d",&S);
        for(int i=1;i<=n;i++)scanf("%d%d",&T[i],&f[i]);
        st[n+1]=sf[n+1]=0;
        for(int i=n;i>=1;i--){
            st[i]=st[i+1]+T[i];
            sf[i]=sf[i+1]+f[i];
        }
        h=t=0;q[t++]=n+1;
        for(int i=n;i>=1;i--){
            while(h+1<t&&up(q[h+1],q[h])<sf[i]*down(q[h+1],q[h]))
                h++;
            dp[i]=getDP(q[h],i);
            while(h+1<t&&up(i,q[t-1])*down(q[t-1],q[t-2])<up(q[t-1],q[t-2])*down(i,q[t-1]))
                t--;
            q[t++]=i;
        }
        printf("%d\n",dp[1]);
    }
    return 0;
}

在这里插入图片描述

posted @ 2020-03-24 07:49  winechord  阅读(90)  评论(0编辑  收藏  举报