首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【IOI2000】邮局设置问题

现在连基础DP都要看题解和代码才能写出来了,怎么办嘛QAQ

原题:

一些村庄建在一条笔直的高速公路边上,我们用一条坐标轴来描述这条公路,每个村庄的坐标都是整数,没有两个村庄的坐标相同。两个村庄的距离定义为坐标之差的绝对值。我们需要在某些村庄建立邮局。使每个村庄使用与它距离最近的邮局,建立邮局的原则是:所有村庄到各自使用的邮局的距离总和最小。
数据规模:1<=村庄数<=300,  1<=邮局数<=30,  1<=村庄坐标<=10000

 

用dis表示若使在i-j中选某点建站,这个点到i-j中每个点距离和的最小值

贪心:选i-j的中点是建站是最优的,可以使用显然法证明(逃

f[i][j]表示一直到第i个点,建了j站的最优质

把j的循坏放外面,也就是先枚举建站的数量,状态转移方程为f[k][j-1]+dis[k+1][i] , j-1<=k<i

意思是枚举把站建在j-1到i的情况

感觉NOIP要挂了,怎么办嘛QAQ

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int n,m,a[110000];
 8 int f[310][310],dis[310][310];
 9 int main(){//freopen("ddd.in","r",stdin);
10     memset(f,10,sizeof(f));
11     cin>>n>>m;
12     for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
13     for(int i=1;i<=n;i++)
14         for(int j=i+1;j<=n;j++)
15             dis[i][j]=dis[i][j-1]+a[j]-a[(i+j)>>1];//贪心,若使一段去间到区间内某点距离和最小,则某点取中点
16     for(int i=1;i<=n;i++){
17         f[i][i]=0;
18         f[i][1]=dis[1][i];
19     }
20     for(int j=2;j<=m;j++)
21         for(int i=j+1;i<=n;i++)
22             for(int k=j-1;k<i;k++)
23                 f[i][j]=min(f[i][j],f[k][j-1]+dis[k+1][i]);
24     cout<<f[n][m]<<endl;
25     return 0;
26 }
View Code

 

posted on 2016-10-12 17:23  cdcq_old  阅读(286)  评论(0编辑  收藏  举报