任务安排(代价提前付)

任务安排

好吧,就只有这道水题.

感觉自己不用博客写出来理解就好像很不深,那这里就不手懒了...

这里我们显然第i批任务前面的时间卡住我们了,导致我们必须设两维,然后就炸了...

这里的思路也是我刚刚接触,代价提前付..

具体点就是我们考虑当前的操作会对之后的状态产生什么影响,提前加上去,这样在后面的转移中就不用考虑前面的影响了,因为前面已经处理过了..

针对这道题,我们主要就被S卡住了,因为这样我们必须枚举j,来维护第几批的信息,这样才能进行转移...

但我们采用之前的思路,考虑我们处理第i批时,那个s对后面造成的影响,因为时间是累加的,所以对于后面的每一批中,单考虑s对代价的影响,就产生了s*(f[n]-f[j-1])的影响,(单考虑这一次s的影响).

然后这样处理之后我们就把s带来的后效性处理掉了,就可以用一维而不必枚举j了...至于处理任务的时间,我们前缀和求一下即可...

其实我们是把试讲分成两部分处理了,一部分是s影响的,一部分是任务的时间。而s则会想象到后面,所以我们在处理当前状态时,就把它带来的影响支付即可...

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5100;
int s,n,T[N],F[N];
ll f[N]; //f[i]表示前i个数分成若干组的最小代价. 
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
int main()
{
    freopen("1.in","r",stdin);
    n=read();s=read();
    for(register int i=1;i<=n;++i) T[i]=T[i-1]+read(),F[i]=F[i-1]+read();
    memset(f,10,sizeof(f));f[0]=0;
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=i;++j) //和i同箱子的起点.
            f[i]=min(f[i],f[j-1]+s*(F[n]-F[j-1])+(F[i]-F[j-1])*T[i]);
    printf("%lld",f[n]);
    return 0;        
}
原文地址:https://www.cnblogs.com/gcfer/p/11789021.html