• 一本通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
  • 相关阅读:
    编写 grunt 插件经验
    Sencha Touch 手机移动开发框架 HTML5 项目压缩方案;
    随笔 编辑推荐 上头条了, 贴出来做个记念!
    Javascript 俄罗斯方块 游戏代码解释!
    30天自制操作系统(NASM+GCC版)
    Logisim 打不开的解决方案(Windows10)
    Kali Linux 2020通过UEFI硬盘安装(免u盘)
    开源一个自制的ORM框架,基于Java原生JDBC(应该是全网首个吧)
    书单
    前端技术文章收集
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10403480.html
Copyright © 2020-2023  润新知