P4072 [SDOI2016]征途(斜率优化)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4072 [SDOI2016]征途(斜率优化)相关的知识,希望对你有一定的参考价值。
把 n n n个数划分为 m m m段,求最小的方差.
设序列和 ∑ i = 1 n x i = S \\sum\\limits_{i=1}^nx_i=S i=1∑nxi=S,最后选取的每段的数字和为 L i L_i Li
D = 1 m ∗ ∑ i = 1 m ( E − L i ) 2 = 1 m ∑ i = 1 m ( E 2 + L i 2 − 2 E ∗ L i ) D=\\frac{1}{m}*\\sum\\limits_{i=1}^m(E-L_i)^2=\\frac{1}{m}\\sum\\limits_{i=1}^m (E^2+L_i^2-2E*L_i) D=m1∗i=1∑m(E−Li)2=m1i=1∑m(E2+Li2−2E∗Li)
其中 E = S m E=\\frac{S}{m} E=mS
m ∗ D = m E 2 + ∑ i = 1 m L i 2 − 2 E ∗ ∑ i = 1 m L i m*D=mE^2+\\sum\\limits_{i=1}^mL_i^2-2E*\\sum\\limits_{i=1}^mL_i m∗D=mE2+i=1∑mLi2−2E∗i=1∑mLi
m ∗ D = m E 2 + ∑ i = 1 m L i 2 − 2 m E 2 m*D=mE^2+\\sum\\limits_{i=1}^mL_i^2-2mE^2 m∗D=mE2+i=1∑mLi2−2mE2
得到 m 2 D = m ∗ ∑ i = 1 m L i 2 − S 2 m^2D=m*\\sum\\limits_{i=1}^mL_i^2-S^2 m2D=m∗i=1∑mLi2−S2
如何最小化 ∑ i = 1 m L i 2 \\sum\\limits_{i=1}^m L_i^2 i=1∑mLi2??
定义 f [ i ] [ k ] f[i][k] f[i][k]表示前 i i i个数分成 j j j段的最小代价
f [ i ] [ k ] = min { f [ j ] [ k − 1 ] + ( p r e i − p r e j ) 2 } f[i][k]=\\min\\{f[j][k-1]+(pre_i-pre_j)^2\\} f[i][k]=min{f[j][k−1]+(prei−prej)2}
f [ i ] [ k ] = f [ j ] [ k − 1 ] + p r e i 2 + p r e j 2 − 2 ∗ p r e i ∗ p r e j f[i][k]=f[j][k-1]+pre_i^2+pre_j^2-2*pre_i*pre_j f[i][k]=f[j][k−1]+prei2+prej2−2∗prei∗prej
2 ∗ p r e i ∗ p r e j + f [ i ] [ k ] − p r e i 2 = f [ j ] [ k − 1 ] + p r e j 2 2*pre_i*pre_j+f[i][k]-pre_i^2=f[j][k-1]+pre_j^2 2∗prei∗prej+f[i][k]−prei2=f[j][k−1]+prej2
把 p r e j pre_j prej看作自变量 x x x,把 f [ j ] [ k − 1 ] + p r e j 2 f[j][k-1]+pre_j^2 f[j][k−1]+prej2看作因变量
那么就是最小化截距,显然维护一个下凸壳即可(我写的是 d o u b l e double double的斜率,别学我)
#include <bits/stdc++.h>
using namespace std;
const int maxn =3e3+10;
int n,m,f[maxn][maxn],pre[maxn],a[maxn];
int head = 1, tail = 0, q[maxn];
int x(int i,int k){ return pre[i]; }
int y(int i,int k){ return f[i][k]+pre[i]*pre[i]; }
double slove(int i,int j,int k)
{
return ( 1.0以上是关于P4072 [SDOI2016]征途(斜率优化)的主要内容,如果未能解决你的问题,请参考以下文章