zoukankan      html  css  js  c++  java
  • POJ-1180 Batch Scheduling 【逆向DP+斜率优化】

    题目链接

    题意

    一台机器有N个物品要处理,每个物品的处理时间是Ti,花费系数是Fi,可以把这N个物品分包处理,打包需要花费时间S,机器每处理完一包物品就会把当前时间显示出来(刚开始处理时时间为0),那么这包中每个物品的花费就是显示的这个时间乘以其花费系数。求处理完所有物品的最小花费。

    分析

    朴素的想法设状态为处理前i个物品的最小花费,但是单考虑前i个物品的花费是有后效性的,因为每新增一个包它的开始时间是由前面分组的组数决定的,所以必须再加一维状态来保存前面分的组数。这样考虑即使优化过后复杂度也至少为O(N2)

    换一种思路,既然前面的情况能够影响后面,那我们逆向DP,设状态dp[i]为第i个到第n个物品的最少花费。这样当前的决策影响的只是前面的结果,就不会有后效性。转移方程为:

    dp[i]=minijndp[j]+(S+time[j]time[i])sum[i])

    其中time是花费时间的前缀和,sum[i]是代价系数的后缀和,斜率优化后可以在O(N)的时间求出答案

    AC代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int maxn=1e4+100;
    
    long long dp[maxn];
    int N,S;
    int times[maxn],sum[maxn];
    int que[maxn],head,tail;
    
    int getx(int j)
    {
        return -times[j-1];
    }
    
    long long gety(int j)
    {
        return dp[j];
    }
    
    int front(int i)
    {
        while(tail-head>=2&&
              gety(que[head+1])-gety(que[head])<=
              (getx(que[head+1])-getx(que[head]))*1LL*sum[i])
                ++head;
        return que[head];
    }
    
    void insert(int i)
    {
        while((tail-head>=2)&&
               (gety(que[tail-1])-gety(que[tail-2]))*(getx(i)-getx(que[tail-1]))>=
               (gety(i)-gety(que[tail-1]))*(getx(que[tail-1])-getx(que[tail-2])))
                --tail;
        que[tail++]=i;
    }
    
    void init()
    {
        tail=head=0;
    }
    
    int main()
    {
        while(scanf("%d",&N)!=EOF)
        {
            scanf("%d",&S);
            times[0]=sum[N+1]=0;
            dp[N+1]=0;
            init();
            for(int i=1;i<=N;++i)
            {
                scanf("%d %d",times+i,sum+i);
                times[i]+=times[i-1];
            }
            for(int i=N;i>=1;--i)
                sum[i]+=sum[i+1];
            insert(N+1);
            for(int i=N;i>=1;--i)
            {
                int j=front(i);
                dp[i]=dp[j]+(S+times[j-1]-times[i-1])*sum[i];
                insert(i);
            }
            cout<<dp[1]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    python基础教程学习笔记十五
    使用win32imageinstall安装ubuntu
    python基础教程学习笔记十四
    python基础教程学习笔记十二
    ztpto图片轮播
    jQuery 获取屏幕高度、宽度
    h5新属性,可编辑的段落 contenteditable=“true”
    奋斗的奴隶博客中的牛逼js小测试
    ps4将图片弄成透明图片
    图片轮播,纯js+css
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580570.html
Copyright © 2011-2022 走看看