动态规划题。模型为给定一条直线上的n个整点坐标,在其中选取p个点作为警亭,使得其余的点到最近的警亭的距离之和最小(下面简称最小距离和)。对输入坐标排序后,用c[i][j]保存最后一个警亭设在第i点,且该点之前还有j个警亭的情况下,第一点到第i点的最小距离和。照此不难写出状态转移方程。
c[i][j]=max{c[k][j-1]+(min(d[i]-d[t],d[t]-d[k]),t=k+1...i-1),k=j-1...i-1}
View Code
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #define INF 0x7fffff
5 #define MIN(a,b) ((a)<(b)?(a):(b))
6 int a[301],c[301][31],n,p;
7 int cmp(const void *a,const void *b)
8 {
9 return *(int *)a-*(int *)b;
10 }
11 int f(int m,int k)
12 {
13 int i,j,tmp,min;
14 if(c[m][k]!=-1) return c[m][k];
15 if(k==0)
16 {
17 tmp=0;
18 for(i=0;i<m;i++) tmp+=a[m]-a[i];
19 c[m][k]=tmp;
20 return tmp;
21 }
22 min=INF;
23 for(i=k-1;i<m;i++)
24 {
25 tmp=0;
26 for(j=i+1;j<m;j++) tmp+=MIN(a[j]-a[i],a[m]-a[j]);
27 min=MIN(min,tmp+f(i,k-1));
28 }
29 c[m][k]=min;
30 return min;
31 }
32 int main()
33 {
34 int i,j,tmp,ans;
35 while(scanf("%d%d",&n,&p)!=EOF)
36 {
37 for(i=0;i<n;i++) scanf("%d",&a[i]);
38 qsort(a,n,sizeof(a[0]),cmp);
39 memset(c,0xff,sizeof(c));
40 ans=INF;
41 for(i=p-1;i<n;i++)
42 {
43 tmp=0;
44 for(j=i+1;j<n;j++) tmp+=a[j]-a[i];
45 ans=MIN(ans,tmp+f(i,p-1));
46 }
47 printf("%d\n",ans);
48 }
49 return 0;
50 }