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 }
View Code
原文地址:https://www.cnblogs.com/137shoebills/p/7783613.html