POJ 1160 Post Office(dp)

来源:互联网 发布:java未来五年发展前景 编辑:程序博客网 时间:2024/05/21 10:40

题目描述:
Post Office
Time Limit: 1000MS Memory Limit: 10000K

There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates.

Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.

You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.

Input
Your program is to read from standard input. The first line contains two integers: the first is the number of villages V, 1 <= V <= 300, and the second is the number of post offices P, 1 <= P <= 30, P <= V. The second line contains V integers in increasing order. These V integers are the positions of the villages. For each position X it holds that 1 <= X <= 10000.

Output
The first line contains one integer S, which is the sum of all distances between each village and its nearest post office.

Sample Input
10 5
1 2 3 6 7 9 11 22 44 50

Sample Output
9

题目大意:
题目大意很简单,就是有v个城市,p个邮局,问这p个邮局建在哪p个村庄里可以让每个村子到最近的邮局的距离的和最小。

题目分析:
首先做完这道题之后觉得这道题还是很不错的,有很大的关于排列组合的学习的意义
我第一眼看见这个题目,是没有思路的,按照想贪心,然后按照我想的贪心的方法去做,确实样例可以但是代码实现起来感觉老费劲了,所以想是不是dp,于是定义:
dp[i][j]:前i个城市放j个邮局和的最小值,可是这样定义了之后,怎么才能找出递推关系呢?实不相瞒,我是参考了别人写的一片博客,对于这篇博客,我给出101分,原因是这个博主跟我一样把详细的思路写出来了,(还有图解)而不是随便沾了一个代码或者简简单单说两句就结束的那种,本来想附上人家的博客地址着,可是这是以前做的题目,一下找不到了,如果博主看到我的话可以告诉我。但是博主的思路我还是记得的
前i个城市放j个邮局,我们拆出来1个邮局,同时把这i个城市分成两部分,0~k放j-1个邮局,k+1~i放1个,这样我们只需要把k从0~i-1循环,取最大值,就可以把所有情况概括,从0~k放j-1个邮局,显然是我们dp数组存储的东西可以直接调用,那么就需要我们把 从a~b放一个邮局的距离和 提前枚举出来就好了,这个枚举的方法就是依此加上一个城市,再用之前得到的值更新就行(看代码就明白了)
代码:

#include "stdio.h"#include "algorithm"using namespace std;#define INF 1e8int pos[300+5];int dp[300+5][30+5];int d[300+5][300+5];int main(){    int v,p,i,j,k;    while(scanf("%d%d",&v,&p)!=EOF)    {        for (i = 1; i <= v; i += 1)        {            scanf("%d",&pos[i]);        }        for(i=1;i<v;i++)        {            for(j=i+1;j<=v;j++)            {                //画图试着就能明白为什么这么写,淡然有别的方法,个人感觉这个好                d[i][j]=d[i][j-1]+pos[j]-pos[(i+j)/2];            }        }        for(i=1;i<=v;i++)        {            for(j=0;j<=p&&j<=i;j++)            {                if(j==0){                    //0个的话就相当于把邮局放在了无穷远                    dp[i][0]=INF;continue;                }                if(i==j){                    dp[i][j]=0;continue;                }                //因为每次都是拿dp当前的值更新,所以对于第一次更新的时候我们把初值定为INF                dp[i][j]=INF;                for(k=j-1;k<i;k++)                {                    dp[i][j]=min(dp[i][j],dp[k][j-1]+d[k+1][i]);                }            }        }        printf("%d\n",dp[v][p]);    }    return 0;}
0 0