【斜率优化】 POJ 1180 Batch Scheduling

时间:2021-09-18 20:01:32

通道

题意:一台机器要按照顺序完成n个任务,每个任务都有一个代价f和需要时间t。机器完成任务的方式是分批处理,对于每一批任务需要首先预处理s时间,同批任务中所有单个任务都是同时完成,代价为完成的时刻乘以各自的代价。求最小代价

思路:

分批考虑情况太多,可以先将问题转化。每个任务对对最后代价的贡献实际上等于它及它以后的f之和乘以它的时间t,即后面的任务都要为它等上t的时间,会多花f*t的代价。

找i的决策点的方法即min(dp[p]+(st[i]-st[p]+s)*sf[i]),st[i]为>=i的时间总和,sf[i]为大于等于i的代价总和,若两个决策点,j,k(j<k),存在j不比k更差,则意味着:

      dp[j]+(st[i]-st[j]+s)*sf[i]<=dp[k]+(st[i]-st[k]+s)*sf[i]   ==>  (dp[j]-dp[k])/(st[j]-st[k])<=sf[i]

      我们记用g(j,k)为用决策点j去取代k的代价函数,即考虑第i个点的时候如果发生了g(j,k)<=sf[i],那么用k就不如用j。

代码:

【斜率优化】 POJ 1180 Batch Scheduling【斜率优化】 POJ 1180 Batch Scheduling
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[12000],st[12000],sf[12000],L[12000];
int main()
{
    int n,s;
    while(scanf("%d%d",&n,&s)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d%d",st+i,sf+i);
        dp[n+1]=st[n+1]=sf[n+1]=0;
        for(int i=n;i>=1;i--)
            st[i]+=st[i+1],sf[i]+=sf[i+1];
        int a=0,b=0;
        L[a]=n+1;
        for(int i=n;i>=1;i--)
        {
            while(a<b&&dp[L[a+1]]-dp[L[a]]<=(st[L[a+1]]-st[L[a]])*sf[i])
                a++;
            dp[i]=dp[L[a]]+(st[i]-st[L[a]]+s)*sf[i];
            while(a<b&&(dp[i]-dp[L[b]])*(st[L[b]]-st[L[b-1]])<=(st[i]-st[L[b]])*(dp[L[b]]-dp[L[b-1]]))
                b--;
            L[++b]=i;
        }
        printf("%d\n",dp[1]);
    }
    return 0;
}
View Code