JZYZOJ1311 邮局设置问题 dp
易得每两个点之间建立邮局的最好位置为两点最中间的点,两点之间如果没有奇数个数的点则中间两个点都可以...(自己画一下图可以看出随着右边点的增大最佳点的增大非常平滑...强迫症一本满足)
w[i][j]为i,j两个点之间建立邮局的最小的距离累加和
则w[i][j]=w[i][j-1]+a[j]-a[(i+j)/2];
相对于前一个的总距离只需要加上新加入的点到最佳点的距离
(因为最佳点移动的非常平滑啊,要么是不动要么是动了之后相对于前一个邮局位置没什么意义(因为两点之间点数为偶数时中间两个点都可以看做最佳点,所以所有点分别到这两个点的距离和是一样的))
自己画图分析吧我画不出来图几何绘图太难用了席八.....
f[j][i]为在前i个点里建立j个邮局的距离累加和
f[j][i]=min(f[j][i],f[j-1][k]+w[k+1][i]);
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int n,m; 8 int a[310]={}; 9 int f[310][310]={}; 10 int w[310][310]={}; 11 int main(){ 12 cin>>n>>m; 13 for(int i=1;i<=n;i++){ 14 cin>>a[i]; 15 } 16 sort(a+1,a+1+n); 17 for(int i=1;i<=n;i++){ 18 for(int j=i+1;j<=n;j++){ 19 w[i][j]=w[i][j-1]+a[j]-a[(i+j)/2]; 20 } 21 } 22 for(int i=1;i<=n;i++){ 23 f[i][i]=0; 24 f[1][i]=w[1][i]; 25 } 26 for(int j=2;j<=m;j++){ 27 for(int i=j+1;i<=n;i++){ 28 f[j][i]=99999999; 29 for(int k=1;k<i;k++){ 30 f[j][i]=min(f[j][i],f[j-1][k]+w[k+1][i]); 31 } 32 } 33 } 34 cout<<f[m][n]<<endl; 35 return 0; 36 }