一本通1607【 例 2】任务安排 2

1607:【 例 2】任务安排 2

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

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

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

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

【输入】

第一行是 N。第二行是 S

下面 N 行每行有一对正整数,分别为 Ti和 Ci ,表示第 i 个任务单独完成所需的时间是 Ti 及其费用系数 Ci 。

【输出】

一个数,最小的总费用。

【输入样例】

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

【输出样例】

153

【提示】

数据范围与提示:

对于全部数据,1N104,0S50,1Ti,Ci100

虽然久了点,但全部都是靠抄了一道板子题后自己的理解做出来的qaq

sol:

dp[i]表示到第i个任务话费的最小值

dp[i]=min(dp[i],dp[j]+S*(Cost[n]-Cost[j])+Time[i]*(Cost[i]-Cost[j]))    ---->(n2做法见例一)


设j<k<i,若k比j优  (Ps:为了方便C表示Cost,T表示Time)

则dp[k]+S*(C[n]-C[k])+T[i]*(C[i]-C[k])<=dp[j]+S*(C[n]-C[j])+T[i]*(C[i]-C[j])

把括号拆掉 dp[k]+S*C[n]-S*C[k]+T[i]*C[i]-T[i]*C[k]<=dp[j]+S*C[n]-S*C[j]+T[i]*C[i]-T[i]*C[j]

消去同类 dp[k]-S*C[k]-T[i]*C[k]<=dp[j]-S*C[j]-T[i]*C[j]

移项得 dp[k]-dp[j]<=(S+T[i])*(C[k]-C[j])    条件1

则(条件1)成立时 k 比 j 优 ,否则 j 比 k 优

(dp[k]-dp[j]) / (C[k]-C[j]) 是斜率

代码应该可以出来了

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('
')
const int N=10005;
int n,S,Time[N],Cost[N];
int dp[N];
int Que[N];
inline bool Panduan(int j,int k,int i)    //j<k<i
{
    int S1=dp[k]-dp[j];
    int S2=(S+Time[i])*(Cost[k]-Cost[j]);
    return (S1<=S2)?(1):(0);
}
inline bool Panduan_Rev(int j,int k,int i) //j<k<i
{
    int S1=(dp[k]-dp[j])*(Cost[i]-Cost[k]);
    int S2=(dp[i]-dp[k])*(Cost[k]-Cost[j]);
    return (S1>=S2)?(1):(0);
}
int main()
{
    int i,Head=1,Tail=1;
    R(n); R(S);
    for(i=1;i<=n;i++)
    {
        Time[i]=Time[i-1]+read();
        Cost[i]=Cost[i-1]+read();
    }
    dp[0]=0; Que[1]=0;
    for(i=1;i<=n;i++)
    {
        while(Head<Tail&&Panduan(Que[Head],Que[Head+1],i)) Head++;
        int j=Que[Head];
        dp[i]=dp[j]+S*(Cost[n]-Cost[j])+Time[i]*(Cost[i]-Cost[j]);
        while(Head<Tail&&Panduan_Rev(Que[Tail-1],Que[Tail],i)) Tail--;
        Que[++Tail]=i;
    }
    Wl(dp[n]);
    return 0;
}
/*
input
5
1
1 3
3 2
4 3
2 3
1 4
output
153
*/
View Code
原文地址:https://www.cnblogs.com/gaojunonly1/p/10403480.html