【BZOJ2726】【SDOI2012】—任务安排(斜率优化dp)

传送门

有一个显然的 O ( n 2 ) d p O(n^2)dp O(n2)dp

f [ i ] f[i] f[i]表示前 i i i天的最小花费
t o t tot tot是费用的前缀和
t t t是时间的前缀和

f [ i ] = m i n ( f [ j ] + ( t o t n − t o t j ) ∗ ( s + t i − t j ) ) f[i]=min(f[j]+(tot_n-tot_j)*(s+t_i-t_j)) f[i]=min(f[j]+(totntotj)(s+titj))
g [ i ] = f [ i ] − t o t n ∗ t i + t o t i ∗ t i − s ∗ t o t j g[i]=f[i]-tot_n*t_i+tot_i*t_i-s*tot_j g[i]=f[i]totnti+totitistotj

考虑2个决策点如果 x x x y y y更优
g [ x ] − g [ y ] t o t x − t o t y ≤ t i \frac{g[x]-g[y]}{tot_x-tot_y}\le ti totxtotyg[x]g[y]ti

那就变成斜率优化的套路了

注意斜率不要直接除,精度要爆炸的
交叉相乘判大小

B Z O J BZOJ BZOJ d o u b l e double double很友好?比 l o n g   l o n g long\ long long long快了接近一倍

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
#define ll long long
#define re register
inline char gc(){
	static char ibuf[RLEN],*ob,*ib;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ob==ib)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=(ch=='-'),ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
const int N=300005;
const double eps=1e-6;
struct point{
    double x,y;
    point(double _x=0,double _y=0):x(_x),y(_y){}
    friend inline point operator -(const point &a,const point &b){
        return point(a.x-b.x,a.y-b.y);
    }
    inline double slope(){
        return x/y;
    }
}p[N];
int n,stk[N],top;
ll f[N],s,tot[N],t[N];
inline void dp(int i,int j){
    f[i]=f[j]+(t[i]-t[j]+s)*(tot[n]-tot[j]);
}
signed main(){
    n=read(),s=read();
    for(re int i=1;i<=n;++i)t[i]=t[i-1]+read(),tot[i]=tot[i-1]+read();
    for(re int i=1;i<=n;++i){
        re int l=1,r=top,res=0;
        while(l<=r){
            int mid=(l+r)>>1;
            point tp=(p[stk[mid]]-p[stk[mid-1]]);
            if(tp.y<=t[i]*tp.x)l=mid+1,res=mid;
            else r=mid-1;
        }
        dp(i,stk[res]);
        p[i].x=tot[i],p[i].y=f[i]-tot[n]*t[i]+tot[i]*t[i]-s*tot[i];
        while(top&&(p[stk[top]]-p[stk[top-1]]).y*(p[i]-p[stk[top]]).x>=(p[i]-p[stk[top]]).y*(p[stk[top]]-p[stk[top-1]]).x)top--;
        stk[++top]=i;
    }
    cout<<f[n];
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值