The main idea: give a series of numbers, divide them into m parts, if the sum of the part I is AI, the 1th part to the section I total has the number of BI, then SUM=A1*B1+A1*B2+...+AM*BM, to find the smallest sum.
First sort, big in front, and then grouped in such order, each group must be consecutive numbers, which can be easily proved by the neighboring Exchange method.
The number of I is divided into J by D[i][j], and the sum of the number of first I is represented by the sum[i], and the enumeration of the part J is recursive.
State transition equation: d[i][j]=min {d[i-u][j-1]+i*sum[i]-sum[u]}
#include <stdio.h> #include <stdlib.h>int a[110];int d[110][110];int sum[110];int Cmpa (const INT*I,CONST INT*J); int main (void) {int i,j,u,p,n,m,pi,qi,minp;scanf ("%d", &pi), for (qi=0;qi<pi;qi++) {scanf ("%d%d", &n , &m); for (i=1;i<=n;i++) {scanf ("%d", &a[i]);} Qsort (A+1,n,sizeof (a[1]), Cmpa); Sum[1]=a[1];for (i=2;i<=n;i++) {sum[i]=sum[i-1]+a[i];} for (i=1;i<=n;i++) {d[i][1]=sum[i]*i;p=i>m?m:i;for (j=2;j<=p;j++) {minp= (1<<30); for (u=1;u<=i;u++ {if (i-u<j-1) {break;} minp=d[i-u][j-1]+ (Sum[i]-sum[i-u]) *i<minp?d[i-u][j-1]+ (sum[i]-sum[i-u]) *i:minp;} D[I][J]=MINP;}} printf ("%.4f\n", (double) d[n][m]/sum[n]);} return 0;} int Cmpa (const int*i,const int*j) {return *j-*i;}
UVA 1456-cellular Network (DP)