ioi2000 poj 1160 VIJOS-P1242 邮局问题

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]);		
}

点赞