zoukankan      html  css  js  c++  java
  • P2134 百日旅行 (斜率优化,DP)

    题目链接


    Solution

    斜率优化(DP). 今天下午才打的第一道题 QwQ...
    (90) 分很简单,一个简单的递推.
    (f[i]) 为最后一天旅游的花费, (g[i]) 为最后一天吃饭的花费.
    转移很简单:
    (f_i=min(f_i,g_j+p*(i-j)^2);)
    (g_i=min(g_i,f_j+q*(i-j));)
    时间复杂度 (O(n^2)),然后看优化.

    对于 (g[i]),可以直接从(1)(i-1)记录一个 (Min(f[j]-q*j)),然后就可以(O(1))转移.
    然后再看 (f[i]),将 (f[i]) 的转移方程整理后得:

    [f[i]+2*p*ij-p*i^2=g[j]+p*j^2 ]

    此时化为 (y=kx+b) 的形式.
    则令 :
    (2*p*j)(x);
    (i)(k);
    (f[i]-p*i)(b) ;
    (g[j]+p*j^2)(y) ;
    且我们发现 (k) 递增,满足斜率优化要求.此处 (g[i],g[j]) 都已经求解出来.
    那么此时我们要使得 (f[i]) 尽量小,也就是使得 (b) 最小.
    然后就是用单调队列维护下凸包找到第一个比 (k) 大的斜率即可.

    Q:为什么找第一个比 (k) 大的斜率??
    此时我们需要使得 (b) 最小,(b=x*(y/x-k)) ,所以要使得 (y/x) 尽量小且大于 (k) 即可.

    时间复杂度 (O(n)).

    Code

    //第一次打不会,只能对着别人打 QwQ...
    #include<bits/stdc++.h>
    #define ll long long
    #define y(i) (g[i]+p*i*i)
    #define x(i) (2*p*i)
    using namespace std;
    const int N=200005;
    int n,r,l,Q[N];
    ll p,q,Min,f[N],g[N];
    int main(){
        cin>>n>>p>>q;
        for(int i=1;i<=n;i++)
        {
            g[i]=Min+q*i;
            while(r>l&&i*(x(Q[l+1])-x(Q[l]))>=y(Q[l+1])-y(Q[l]))l++;
            f[i]=g[Q[l]]+p*(i-Q[l])*(i-Q[l]);
            Min=min(Min,f[i]-q*i);
            while(r>l&&(y(i)-y(Q[r]))*(x(Q[r])-x(Q[r-1]))<=(x(i)-x(Q[r]))*(y(Q[r])-y(Q[r-1])))r--;
            Q[++r]=i;
            //单调队列维护第一个比 k 大的斜率.
        }
        printf("%lld
    ",min(f[n],g[n]));
        return 0;
    }
    
  • 相关阅读:
    Rsync企业实战之自动异地备份(转)
    Linux启动过程详解 (转)
    Linux系统下修改环境变量PATH路径的三种方法
    linux更改启动级别后,无法启动的问题解决
    MySQLAdmin用法
    mysql toolkit 用法[备忘] (转)
    mysql edit
    MySQL中SSL配置
    mysql ALTER COLUMN MODIFY COLUMN CHANGE COLUMN 区别及用法 (转)
    MySQL 使用mysqld_multi部署单机多实例详细过程 (转)
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9714073.html
Copyright © 2011-2022 走看看