Description
一些村庄建在一条笔直的高速公路边上,我们用一条座标轴来描述这条公路,每个村庄的座标都是整数,没有两个村庄的座标相同。两个村庄的距离定义为座标之差的绝对值。我们需要在某些村庄建立邮局。使每个村庄使用与它距离最近的邮局,建立邮局的原则是:所有村庄到各自使用的邮局的距离总和最小。 数据规模:1< =村庄数< =300, 1< =邮局数< =30, 1< =村庄座标< =10000
Input
2行 第一行:n m {表示有n个村庄,建立m个邮局} 第二行:a1 a2 a3 .. an {表示n个村庄的座标}
Output
1行 第一行:l {l表示最小距离总和}
Sample Input
10 5
1 2 3 6 7 9 11 22 44 50
Sample Output
9
Source
IOI2000 第五题
状态:f[i][j]: 在前 i 个村庄中建立 j 个邮局的最小耗费
f[i][j] = min(f[i][j],f[k][j-1]+sum[k+1][i]);
sum[i][j]: 在第 i 个村庄到第 j 个村庄中建立 1 个邮局的最小耗费,在 i 和 j 建立一个邮局位置为 (i+j)/2。
注意初始化
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[301];
int sum[301][301];
int f[301][301];
int main()
{
int n,m,i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
sum[i][j]=sum[i][j-1]+a[j]-a[(i+j)/2];
memset(f,1,sizeof(f));
for(i=1;i<=n;i++)
{
f[i][i]=0;
f[i][1]=sum[1][i];
}
for(j=2;j<=n;j++)
for(i=j+1;i<=n;i++)
for(k=j-1;k<i;k++)
f[i][j]=min(f[i][j],f[k][j-1]+sum[k+1][i]);
printf("%d",f[n][m]);
}