zoukankan      html  css  js  c++  java
  • 浅谈“任务安排”

    任务安排1

    初步思考可以得出一个(O(n^3))的dp做法
    f[i][j]表示前i个任务,分成j段的最小费用
    求出t和c的前缀和sumt[i]和sumc[i]
    (f[i][j]=min{f[k][j-1]+(s*j+sumt[i])*(sumc[i]-sumc[k])})

    我们可以考虑把启动时间累加到后面所有任务的总时间上去
    设f[i]表示前i个任务分成若干批执行的最小费用
    (f[i]=min{f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j])}(0<=j<i))
    复杂度(O(n^2))
    这是一种费用提前计算的经典思想

    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int N=5020;
    int n,s,f[N],sumc[N],sumt[N];
    signed main()
    {
    	n=read(),s=read();
    	for(int i=1;i<=n;++i)
    	{
    		int t=read(),c=read();
    		sumt[i]=sumt[i-1]+t;
    		sumc[i]=sumc[i-1]+c;
    	}
    	memset(f,0x3f3f3f,sizeof(f));
    	f[0]=0;
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<i;++j)
    			f[i]=min(f[j]+sumt[i]*(sumc[i]-sumc[j])+s*(sumc[n]-sumc[j]),f[i]);
    	cout<<f[n];
    	return 0;
    }
    

    任务安排2


    上图来自心里没有一点AC数

    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int N=3e5+2020;
    int n,s;
    int sumc[N],sumt[N];//前缀和数组 
    int f[N];//dp数组 
    int q[N];//维护下凸壳的队列 
    signed main()
    {
    	n=read(),s=read();
    	for(int i=1;i<=n;++i) 
    	{
    		int t=read(),c=read();
    		sumc[i]=sumc[i-1]+c;
    		sumt[i]=sumt[i-1]+t;
    	}
    	memset(f,0x3f,sizeof(f));
    	f[0]=0;int l=1,r=1;
    	q[1]=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[n];
    	return 0;
    }
    

    任务安排3

    acwing是本题数据会溢出long long ,建议去loj

    和上一道题不同的是t可能是负数,所以横坐标sumt不在具有单调性,导致需要最小化截距的直线的斜率
    (s+sumt[i])不在具有单调性,所以不能只保留凸壳上大于(s+sumt[i])的部分了。而是需要维护整个凸壳
    可以在单调队列里二分查找一个位置p,让左侧线段斜率比(s+sumt[i])大,右边比(s+sumt[i])
    (p)即为最优决策,然后更新(f[i])即可
    Loj可过

    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    const int N=5e5+2021;
    int n,s;
    int l,r;
    int sumt[N],sumc[N],f[N],q[N];
    int search(int i,int k)
    {
    	if(l==r) return q[l];
    	int L=l,R=r;
    	while(L<R)
    	{
    		int mid=(L+R)>>1;
    		if(f[q[mid+1]]-f[q[mid]]<=k*(sumc[q[mid+1]]-sumc[q[mid]])) L=mid+1;
    		else R=mid;
    	}
    	return q[L];
    }
    signed main()
    {
    	n=read(),s=read();
    	for(int i=1;i<=n;++i) 
    	{
    		int t=read(),c=read();
    		sumt[i]=sumt[i-1]+t;
    		sumc[i]=sumc[i-1]+c;
    	}
    	l=1,r=1;q[1]=0;
    	for(int i=1;i<=n;++i)
    	{
    		int p=search(i,s+sumt[i]);
    		f[i]=f[p]-(s+sumt[i])*sumc[p]+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[n];
    	return 0;
    
    }
    
  • 相关阅读:
    20162307 实验二实验报告
    20162307 第六周学习总结
    20162307 第5周学习总结
    20162306 2016-2017-2《程序设计与数据结构》第八周学习总结
    20162306 2016-2017-2《程序设计与数据结构》第七周学习总结
    第二次实验报告
    20162306 2016-2017-2《程序设计与数据结构》第六周学习总结
    20162306 2016-2017-2《程序设计与数据结构》第五周学习总结
    第一次实验报告
    20162306陈是奇 2016-2017-2《程序设计与数据结构》第四周学习总结
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/12665204.html
Copyright © 2011-2022 走看看