zoukankan      html  css  js  c++  java
  • P4072 [SDOI2016](BZOJ4518) 征途 [斜率优化DP]

    题目描述

    Pine开始了从S地到T地的征途。

    从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。

    Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。

    Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。

    帮助Pine求出最小方差是多少。

    设方差是v,可以证明,v imes m^2v×m2是一个整数。为了避免精度误差,输出结果时输出v imes m^2v×m2。

    输入格式

    第一行两个数 n、m。

    第二行 n 个数,表示 n 段路的长度

    输出格式

    一个数,最小方差乘以 m^2m2 后的值

    输入输出样例

    输入 #1
    5 2
    1 2 5 8 6
    输出 #1
    36

    说明/提示

    对于 30% 的数据,1n10

    对于 60% 的数据,1n100

    对于 100% 的数据,1n3000

    保证从 S 到 T 的总路程不超过 30000 。


    题解:题目意思是n段路每段路有一个长度,分m次走完,让你求这m次的方差乘以m^2的最小值。
     
    参考代码:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=30010;
    int n,m,q[maxn];
    ll f[maxn],g[maxn],sum[maxn],val;
    inline ll X(int i){return sum[i];}
    inline ll Y(int i){return (g[i]+sum[i]*sum[i]);}
    inline double slope(int x,int y){return 1.0*(Y(y)-Y(x))/(X(y)-X(x));}
    
    
    int main()
    {
        scanf("%d%d",&n,&m); sum[0]=0;
        for(int i=1;i<=n;++i)
        {
            scanf("%lld",&val);
            sum[i]=sum[i-1]+val;
            g[i]=sum[i]*sum[i];
        }
    
        for(int i=1;i<m;++i)//m days
        {
            int l=0,r=0;q[0]=i;
            for(int j=i+1;j<=n;++j)// n roads
            {
                while(l<r&&slope(q[l],q[l+1])<2.0*sum[j])++l;
                f[j]=g[q[l]]+(sum[j]-sum[q[l]])*(sum[j]-sum[q[l]]);
                while(l<r&&slope(q[r-1],q[r])>slope(q[r-1],j)) --r;
                q[++r]=j;
            }
            for(int j=1;j<=n;++j) g[j]=f[j];
        }
        printf("%lld
    ",m*f[n]-sum[n]*sum[n]);
    
        return 0;
    }
    View Code
  • 相关阅读:
    UI/UE对个性化推荐的影响
    毫秒转换为天、小时、分、秒
    查生字
    探秘推荐引擎之协同过滤算法小综述
    给文献添加上标
    雅可比迭代和高斯赛德尔迭代
    广义二项式定理求解系数
    关于最大流的EdmondsKarp算法详解
    海量数据处理利器之布隆过滤器
    [leetcode] Path sum路径之和
  • 原文地址:https://www.cnblogs.com/csushl/p/11381804.html
Copyright © 2011-2022 走看看