• 【题解】Luogu P5468 [NOI2019]回家路线


    原题传送门

    前置芝士:斜率优化 不会的可以去杜神博客

    这道题我考场上只会拆点跑最短路的70pts做法

    后来回家后发现错误的爆搜都能拿满分(刀片)

    还有很多人(O(mt))过的,还是要坚持写正解好不好

    我们先考虑(O(mt))的暴力dp,先不考虑总时间对烦躁值的影响,设(dp[id])表示走完第(id)条边最小的代价:

    [dp[id]=Min(dp[j]+A(p_{id}-q_j)^2+B(p_{id}-q_j)+C)(id,j in [1,m],q_j<=p_{id},v[j]=u[id]) ]

    看着这个方程有平方项考虑展开,展开后会发现能转化成斜率优化标准形式

    [dp[j]+Aq_j^2-Bq_j=2Ap_iq_j+dp[i]-Ap_i^2-Bp_i-C ]

    其中(y=dp[j]+Aq_j^2-Bq_j,k=2Ap_i,x=q_j,b=dp[i]-Ap_i^2-Bp_i-C)

    每条边进出一次队列,所以复杂度为(O(m))

    完整代码

    #include <bits/stdc++.h>
    #define N 200005
    #define ll long long
    #define db double
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register ll x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int Max(register int a,register int b)
    {
        return a>b?a:b;
    }
    inline ll Min(register ll a,register ll b)
    {
        return a<b?a:b;
    }
    struct node{
        ll x,y;
        int id;
    };
    int n,m,A,B,C,maxT=0;
    int x[N],y[N],p[N],q[N],head[N];
    ll ans=1926081700000000ll,dp[N];
    vector<int> d[1005];
    vector<node>que[N];
    queue<int> res[1005];
    inline db gslope(register node a,register node b)
    {
        return 1.0*(a.y-b.y)/(1.0*(a.x-b.x));
    }
    inline void ins(register int id)
    {
        int pos=y[id];
        node now=(node){q[id],dp[id]+A*q[id]*q[id]-B*q[id],id};
        while(que[pos].size()-head[pos]>=2)
        {
            int len=que[pos].size();
            if(gslope(que[pos][len-1],que[pos][len-2])<gslope(que[pos][len-2],now))
                break;
            que[pos].pop_back();
        }
        que[pos].push_back(now);
    }
    inline void del(register db slpe,register int pos)
    {
        while(que[pos].size()-head[pos]>=2)
        {
            if(gslope(que[pos][head[pos]],que[pos][head[pos]+1])>slpe)
                return;
            ++head[pos];
        }
    }
    int main()
    {
        n=read(),m=read(),A=read(),B=read(),C=read();
        for(register int i=1;i<=m;++i)
            x[i]=read(),y[i]=read(),p[i]=read(),q[i]=read(),maxT=Max(maxT,q[i]);
        for(register int i=1;i<=m;++i)
            d[p[i]].push_back(i);
        que[1].push_back((node){0,0,0});
        for(register int t=0;t<=maxT;++t)
        {
            while(!res[t].empty())
                ins(res[t].front()),res[t].pop();
            int len=d[t].size();
            for(register int k=0;k<len;++k)
            {
                int id=d[t][k];
                int pos=x[id];
                if(que[pos].size()==head[pos])
                    continue;
                db slpe=2.0*A*p[id];
                del(slpe,pos);
                int j=que[pos][head[pos]].id;
                dp[id]=dp[j]+1ll*A*(p[id]-q[j])*(p[id]-q[j])+1ll*B*(p[id]-q[j])+C;
                res[q[id]].push(id);
                if(y[id]==n)
                    ans=Min(ans,dp[id]+q[id]);
            }
        }
        write(ans);
        return 0;
    }
    
  • 相关阅读:
    限制转交订单-采购直接批准PO
    限制更改采购订单的供应商地点
    限制采购订单行数量的小数位
    加工费采购订单批准后禁止更改订单数量
    限制ITEM读取其它物料的物料描述
    采购订单限制订单“行号”过大的控制
    限制行表新增记录
    采购订单行需求时间必输
    报价单内,同一物料只允许一条行价格记录
    限制头表新增记录
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/11198638.html
Copyright © 2020-2023  润新知