zoukankan      html  css  js  c++  java
  • 任务安排 2

    https://loj.ac/problem/10185

    题目描述

      有(N)个任务,每个任务有一定的完成时间(T_i)和费用系数(C_i),每一批任务完成的时间为启动时间(S)加上完成的总时间,费用这个任务为所在批次的完成时间乘上它的费用系数,求最小代价。

    思路

      比较容易得到一个(N^3)(dp),我们考虑暴力枚举任务和批次,令(f[i][j])表示前(i)个任务分成(j)批的最小代价,在预处理完前缀和之后,那么(f[i][j]=min{f[k][j-1]+(j*S+sumT[j]-sumT[k])*(sumC[j]-sumC[k])}),直接求即可。

      考虑前一个做法中批次并没有关键的用途,我们需要的仅仅是机器的启动次数,用滚动数组优化空间后,考虑到每次启动都会对后续有影响,我们可以直接计算这个费用。令(f[i])表示前(i)个任务的最小花费(包括后续影响),那么(f[i]=min{f[j]+sumT[i]*(sumC[i]-sumC[j])+S*(sumC[n]-sumC[j])}),复杂度为(N^2)

      我们再进行优化,去掉小括号,并化简,可得:

    [f[j]=(sumT[i]+S)sumC[j]+f[i]-sumT[i]*sumC[i]-S*sumC[n] ]

      这样我们就可以看做一个与(j)相关的一次函数,每个点为((sumC[j],f[j])),对于当前的(i),由于除(f[i])都是确定的,我们只要让直线的截距最小即可,这个可以通过维护下凸壳来实现,复杂度为(O(N))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+10;
    
    int read()
    {
    	int res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    
    int sumt[N],sumc[N],f[N],q[N];
    int main()
    {
    	int n=read(),s=read();
    	for(int i=1;i<=n;i++)
    		sumt[i]=sumt[i-1]+read(),
    		sumc[i]=sumc[i-1]+read();
    	int l=0,r=0;
    	for(int i=1;i<=n;i++)
    	{
    		while(l<r&&(f[q[l+1]]-f[q[l]])<=(s+sumt[i])*(sumc[q[l+1]]-sumc[q[l]]))l++;
    		f[i]=f[q[l]]-(s+sumt[i])*sumc[q[l]]+sumt[i]*sumc[i]+s*sumc[n];
    		while(l<r&&(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])>=(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]]))
    			r--;
    		q[++r]=i;
    //		cout<<f[i]<<endl;
    	}
    	printf("%d
    ",f[n]);
    }
    
  • 相关阅读:
    Sass开发环境搭建
    三款Javascript SPAs框架资料整理和总结
    Web纯前端“旭日图”实现元素周期表
    能在多种前端框架下使用的表格控件
    控件使用经验-MVP模式+控件封装
    最好的Angular2表格控件
    跨平台开发的两种方法及其对比
    是时候 UWP 了 !
    你的系统也可以拥有“数据透视表”功能!
    Xamarin 免费了,你能做什么?
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11853045.html
Copyright © 2011-2022 走看看