标签:
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 3984 Accepted Submission(s): 1527
【思路】
斜率优化+分配式DP。
设f[i][j]表示将前i个分作j个集合所得最小消费,则有转移方程式:
f[i][j]=min{ f[k][j-1]+(A[k]-A[j+1])^2 }
若有k>l,且决策k优于决策l则有:
f[k][j-1]-f[l][j-1]+sq(A[k+1])-sq(A[l+1]) <= 2*(A[k+1]-A[l+1])*A[i]
先进行j循环枚举f[][j],每一层维护一个单调队列即可。
乘除耗费时间悬殊,如果直接除这个题就超时了。
【代码】
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 6 typedef double Do; 7 const int N = 1e4+10; 8 const int M = 5000+10; 9 10 int f[N][M],A[N],q[N]; 11 int n,m,L,R; 12 int sq(int x) { return x*x; } 13 int UP(int l,int k,int j) { 14 return f[k][j-1]-f[l][j-1]+sq(A[k+1])-sq(A[l+1]); 15 } 16 int DN(int l,int k,int j) { 17 return 2*(A[k+1]-A[l+1]); 18 } 19 void read(int& x) { 20 char c=getchar(); while(!isdigit(c)) c=getchar(); 21 x=0; while(isdigit(c)) x=x*10+c-‘0‘ , c=getchar(); 22 } 23 int main() { 24 int T,kase=0; 25 read(T); 26 while(T--) { 27 read(n),read(m); 28 for(int i=1;i<=n;i++) read(A[i]); 29 sort(A+1,A+n+1); 30 for(int i=1;i<=n;i++) f[i][1]=sq(A[i]-A[1]); //初始化第一层 31 for(int j=2;j<=m;j++) { 32 L=R=0; 33 for(int i=1;i<=n;i++) { 34 while(L<R && UP(q[L],q[L+1],j)<=A[i]*DN(q[L],q[L+1],j)) L++; 35 int t=q[L]; 36 f[i][j]=f[t][j-1]+sq(A[i]-A[t+1]); 37 while(L<R && UP(q[R-1],q[R],j)*DN(q[R],i,j)>=UP(q[R],i,j)*DN(q[R-1],q[R],j)) R--; 38 q[++R]=i; 39 } 40 } 41 printf("Case %d: %d\n",++kase,f[n][m]); 42 } 43 return 0; 44 }
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5119583.html