• P2365 任务安排 题解


    link

    P2365 任务安排

    Solve

    这道题有弱化版和强化版,这道题是弱化版

    我们很容易能想到一个(DP)方程(F[p][i])表示前(i)个取了(p)段的最优解,于是转移方程

    [F[p][i]=min(F[p-1][j]+(ST[i]+past S)ast (SF[i]-SF[j])) ]

    这个转移方程是(O(n^3))的考虑怎么优化

    对于每次转移时间都要加上一个(p)我们提前记录下(p)的费用

    在每一次转移方程时能预判到后面(j-N)的时间都要加上(p)

    于是转移方程就能化到(O(n^2))了,可以过了

    [F[i]=min(F[j]+ST[i]ast (SF[j]-SF[i])+S ast (SF[N]-SF[j])) ]

    但是仅仅优化到这里是不够了

    观察到可以用斜率优化来优化到(O(n))

    转化一下式子

    [(S+ST[i])ast SF[j]+(dp[i]-ST[i]ast SF[i]- Sast SF[i])=(dp[j]) ]

    观察到(S+ST{i])单调递增,(SF[i])单调递增

    所以用单调队列就好了

    Code

    (O(n^2))

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5005;
    int N,S,t[maxn],f[maxn],s_t[maxn],s_f[maxn],dp[maxn];
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f; 
    }
    int main(){
    	freopen("P2365.in","r",stdin);
    	freopen("P2365.out","w",stdout);
    	N=read();S=read();
    	for(int i=1;i<=N;i++)t[i]=read(),f[i]=read();
    	for(int i=1;i<=N;i++)s_t[i]=s_t[i-1]+t[i],s_f[i]=s_f[i-1]+f[i];
    	memset(dp,63,sizeof dp);dp[0]=0;
    	for(int i=1;i<=N;i++)
    	for(int j=0;j<=i;j++){
    		dp[i]=min(dp[j]+s_t[i]*(s_f[i]-s_f[j])+S*(s_f[N]-s_f[j]),dp[i]);
    	}
    	printf("%d
    ",dp[N]);
    	return 0;
    }
    

    (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=10005;
    int N,S,s_f[maxn],s_t[maxn],hed=1,til,F[maxn],Q[maxn];
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f; 
    }
    int X(int j){return s_f[j];}
    int Y(int j){return F[j]-S*s_f[j];}
    long double calc(int i,int j){return (long double)(Y(j)-Y(i))/(X(j)-X(i));}
    
    int main(){
    	freopen("P2365.in","r",stdin);
    	freopen("P23650.out","w",stdout);
    	N=read(),S=read();
    	for(int i=1;i<=N;i++)s_t[i]=s_t[i-1]+read(),s_f[i]=s_f[i-1]+read();
    	Q[++til]=0;
    	for(int i=1;i<=N;i++){
    		while(hed<til&&calc(Q[hed],Q[hed+1])<=((s_t[i])))++hed;
    		int j=Q[hed];F[i]=F[j]+s_t[i]*(s_f[i]-s_f[j])+S*(s_f[N]-s_f[j]);
    		while(hed<til&&calc(Q[til-1],Q[til])>=calc(Q[til-1],i))--til;
    		Q[++til]=i;
    	}
    	printf("%d
    ",F[N]);
    	return 0;
    }
    
  • 相关阅读:
    Java实习二
    Java实习一
    从0开始 Java实习 黑白棋
    从0开始 Java学习 packet用法
    解题报告:hdu 1276 士兵队列训练问题
    从0开始 数据结构 AC自动机 模板(from kkke)
    从0开始 数据结构 AC自动机 hdu 2222
    从0开始 数据结构 字典树 hdu1251
    从0开始 图论学习 拓扑排序 链式前向星表示法
    ui爬虫工具-未完成
  • 原文地址:https://www.cnblogs.com/martian148/p/14057981.html
Copyright © 2020-2023  润新知