zoukankan      html  css  js  c++  java
  • [SDOI2016]征途

    XIII.[SDOI2016]征途

    这题已经在我的任务列表里吃了大半年的灰了……(去年7月加进来的,到现在已经8个月了)

    开始推式子。

    我们设第\(i\)天的路程是\(l_i\)

    则我们的目的是最小化

    \(s^2=\sum\limits_{i=1}^m\dfrac{(\overline{l}-l_i)^2}{m}\)

    代入平均值的定义

    \(s^2=\dfrac{\sum\limits_{i=1}^m\bigg(\tfrac{\sum\limits_{j=1}^ml_j}{m}-l_i\bigg)^2}{m}\)

    暴力展开平方项

    \(s^2=\dfrac{\sum\limits_{i=1}^m\bigg(\dfrac{\sum\limits_{j=1}^ml_j}{m}\bigg)^2-2*l_i*\dfrac{\sum\limits_{j=1}^ml_j}{m}+l_i^2}{m}\)

    分离\(\Sigma\)

    \(s^2=\dfrac{m\bigg(\dfrac{\sum\limits_{j=1}^ml_j}{m}\bigg)^2-2*\sum\limits_{i=1}^ml_i*\dfrac{\sum\limits_{j=1}^ml_j}{m}+\sum\limits_{i=1}^ml_i^2}{m}\)

    稍作整合

    \(s^2=\dfrac{\dfrac{(\sum\limits_{j=1}^ml_j)^2}{m}-2*\dfrac{(\sum\limits_{j=1}^ml_j)^2}{m}+\sum\limits_{i=1}^ml_i^2}{m}\)

    合并

    \(s^2=\dfrac{-\dfrac{(\sum\limits_{j=1}^ml_j)^2}{m}+\sum\limits_{i=1}^ml_i^2}{m}\)

    乘以\(m^2\)

    \(s^2m^2=-(\sum\limits_{j=1}^ml_j)^2+m\sum\limits_{i=1}^ml_i^2\)

    右边的等式中,左边是定值(等于总路程的平方);右边则要我们最小化\(\sum\limits_{i=1}^ml_i^2\)

    \(f[i][j]\)表示:前\(i\)天内分成了\(j\)段的最小平方和。再设\(s_i\)表示路程的前缀和。

    则有\(f[i][j]=\min\limits_{k=0}^{i-1}\{f[k][j-1]+(s_i-s_k)^2\}\)

    可以\(n^2m\)的进行暴力DP,能拿到\(60\%\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,s[3010],f[3010][3010];
    int main(){
    	scanf("%d%d",&n,&m),memset(f,0x3f3f3f3f,sizeof(f));
    	for(int i=1;i<=n;i++)scanf("%d",&s[i]),s[i]+=s[i-1];
    	f[0][0]=0;
    	for(int i=1;i<=n;i++)for(int j=1;j<=min(i,m);j++)for(int k=0;k<i;k++)f[i][j]=min(f[i][j],f[k][j-1]+(s[i]-s[k])*(s[i]-s[k]));
    	printf("%d\n",m*f[n][m]-s[n]*s[n]);
    	return 0;
    } 
    

    我们尝试按段数DP,而不是按天数DP。即,在\(f[i][j]\)中,优先枚举\(j\)

    在枚举\(j\)后,我们就可以暂时忽略\(j\)这一维了。

    我们有\(f[i]=\min\limits_{j=0}^{i-1}\{F[j]+(s_i-s_j)^2\}\)。其中,这个\(F[j]\)是上一轮DP时的\(f\)值,即原本的\(f[i][j-1]\)(注意这个\(j\)和上面递推式里面的枚举的\(j\)不是同一个\(j\)

    假设\(j<k<i\),且\(j\)\(k\)优,

    则有

    \(F[j]+(s_i-s_j)^2<F[k]+(s_i-s_k)^2\)

    暴力展开

    \(F[j]+s_i^2-s_is_j+s_j^2<F[k]+s_i^2-s_is_k+s_k^2\)

    合并同类项

    \(F[j]-s_is_j+s_j^2<F[k]-s_is_k+s_k^2\)

    移项

    \(F[j]-F[k]+s_j^2-s_k^2<s_is_j-s_is_k\)

    提一下

    \(F[j]-F[k]+s_j^2-s_k^2<s_i(s_j-s_k)\)

    除过去(注意\(s_j-s_k\)是负的!!!)

    \(\dfrac{F[j]-F[k]+s_j^2-s_k^2}{s_j-s_k}>s_i\)

    左边的东西与\(i\)无关;右边的东西单调增;

    那不就可以了吗!!!

    维护下凸壳,直接斜率优化硬套,完事。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,s[3010],f[3010][3010],q[3010],l,r;
    int main(){
    	scanf("%d%d",&n,&m),memset(f,0x3f3f3f3f,sizeof(f));
    	for(int i=1;i<=n;i++)scanf("%d",&s[i]),s[i]+=s[i-1];
    	f[0][0]=0;
    	for(int j=1;j<=m;j++){
    		l=r=0;
    		for(int i=1;i<=n;i++){
    			while(r-l&&f[q[l]][j-1]-f[q[l+1]][j-1]+s[q[l]]*s[q[l]]-s[q[l+1]]*s[q[l+1]]>=2*s[i]*(s[q[l]]-s[q[l+1]]))l++;
    			f[i][j]=f[q[l]][j-1]+(s[i]-s[q[l]])*(s[i]-s[q[l]]);
    			while(r-l&&(f[q[r-1]][j-1]-f[q[r]][j-1]+s[q[r-1]]*s[q[r-1]]-s[q[r]]*s[q[r]])*(s[q[r]]-s[i])>=(f[q[r]][j-1]-f[i][j-1]+s[q[r]]*s[q[r]]-s[i]*s[i])*(s[q[r-1]]-s[q[r]]))r--;
    			q[++r]=i; 
    		}
    	}
    	printf("%d\n",m*f[n][m]-s[n]*s[n]);
    	return 0;
    } 
    

  • 相关阅读:
    Spring Cloud Hystrix Dashboard的使用 5.1.3
    Spring Cloud Hystrix 服务容错保护 5.1
    Spring Cloud Ribbon 客户端负载均衡 4.3
    Spring Cloud 如何实现服务间的调用 4.2.3
    hadoop3.1集成yarn ha
    hadoop3.1 hdfs的api使用
    hadoop3.1 ha高可用部署
    hadoop3.1 分布式集群部署
    hadoop3.1伪分布式部署
    KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
  • 原文地址:https://www.cnblogs.com/Troverld/p/14596881.html
Copyright © 2011-2022 走看看