Pine开始了从S地到T地的征途。
从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。
Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。
Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。
帮助Pine求出最小方差是多少。
设方差是v,可以证明,v×m^2是一个整数。为了避免精度误差,输出结果时输出v×m^2。
标签:
一个数,最小方差乘以 m^2 后的值
1≤n≤3000,保证从 S 到 T 的总路程不超过 30000
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=Getchar(); for(;!isdigit(c);c=Getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=Getchar()) x=x*10+c-‘0‘; return x*f; } typedef long long ll; const int maxn=3010; const ll inf=1ll<<60; ll f[2][maxn],S[maxn]; int n,m,x,cur,Q[maxn]; double slop(int x,int y) {return (double)(f[cur^1][x]+S[x]*S[x]-f[cur^1][y]-S[y]*S[y])/(2*S[x]-2*S[y]);} ll getdp(int k,int i) {return f[cur^1][k]+S[k]*S[k]-2*S[k]*(S[i]-x);} int main() { n=read();m=read(); rep(i,1,n) S[i]=S[i-1]+read()*m; x=S[n]/m; rep(i,1,n) f[0][i]=inf; rep(j,1,m) { cur^=1;int l=1,r=0; rep(i,j,n) { while(l<r&&slop(Q[r-1],Q[r])>=slop(Q[r],i-1)) r--;Q[++r]=i-1; while(l<r&&getdp(Q[l],i)>=getdp(Q[l+1],i)) l++; f[cur][i]=getdp(Q[l],i)+(S[i]-x)*(S[i]-x); } } printf("%lld\n",f[cur][n]/m); return 0; }
标签:
原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/5486476.html