POJ 1060 Post Office 分析&解题报告

来源:互联网 发布:淘宝c店怎么运营 编辑:程序博客网 时间:2024/06/05 17:29
 
题目:
Post Office
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 11054 Accepted: 5949

Description

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 51 2 3 6 7 9 11 22 44 50

Sample Output

9

Source

IOI 2000
 
先给出这个让我郁闷了一天的转移方程 DP[i][j]=min{DP[i-1][k]+D[k+1][j]}
 
本题是一个经典的DP题,网上很多解题报告只给出了状态转移方程,或者就给一点点解释,让很多读者茫然这么做的缘由和正确性。下面是我自己的分析。希望读者能看懂。
 
题意很明显不解释了。直接切入正题。
 
对于DP新手来说,本题的DP思路不好想。原因之一就是村庄选邮局要根据距离远近来选,在没有确定最终方案前我怎么知这些村庄离哪个邮局最近?!确实如此。。。
 
那怎么么办?如何DP?
 
让我们来变化一下这个问题(为了下面描述方便,我就正式命名这个变化后的问题为,邮局问题·改),如果去掉村庄要选离最近邮局这个条件,就直接让你来确定哪个村庄选哪个邮局使最终结果最好。那这样就好做了。仔细分析后可以发现,这个问题和原题的最优方案肯定是一样的。邮局问题·改要想最优,必定要让每个村庄选择离它最近的那个邮局,不然就会有更好的方案。也就是说,邮局问题·改的最优解必然包含原问题去掉的条件。
 
不用考虑这个棘手的条件就好办了,从邮局问题·改入手,那个开头给出的转移方程就好理解了。
 
为了方便描述邮局问题·改,我们用覆盖这一词。
 
转移方程解释:
DP[i][j]表示用前i个邮局覆盖前j个村庄的最优解。D[i][j]表示用一个邮局覆盖村庄村庄i,j之间的所有村庄(包括i,j)的最优解。
 
阶段就是不断增加新的邮局去覆盖村庄。
 
最优子结构描述:
假设已知前i个邮局覆盖前j个村庄的最优解方案,即DP[i][j],该方案中的前i-1个邮局覆盖了前k个村庄(子方案1),第i个邮局覆盖了k+1到j的所有村庄(子方案2),那么这两个子方案必然是最优。满足最优子结构性质。那么在求DP[i][j]时,由于不知道k的值,我们只要枚举k的值并取最优子解就好了。
 
问什么求D[i][j]时,邮局一定在(i+j)/2的位置上?这个证明其实很简单,自己画图就可以发现并列出一不等式然后就很容易得出这个结论了。记得有一个北大的ppt上面有推导,无所谓,反正很容易。。。
 
代码:
没任何优化,比如什么四边形不等式啥的,poj  63MS AC...(注意要预处理求D[i][j],不然会900MS+)

#include<iostream>
#include<fstream>
#include<cmath>
using namespace std;

#define MAX 100000000;

int dp[31][301];
int coordinate[301];
int d[301][301];
int V;
int P;

int main()
{
    //ifstream cin("in.txt");
    //ofstream cout("out.txt");
    while(cin>>V>>P)
    {
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=V;i++)
    cin>>coordinate[i];
   

    //预处理求d[i][j]
    for(int i=1;i<=V;i++)
    for(int j=i;j<=V;j++)
    for(int k=i;k<=j;k++)
    d[i][j]+=abs(coordinate[k]-coordinate[(i+j)/2]);
    

    //初始状态 
    for(int i=1;i<=V;i++)
    {
    int t=0;
    for(int j=1;j<=i;j++)
    t+=abs(coordinate[j]-coordinate[i/2+1]);
    dp[1][i]=t;
    }
 
    for(int i=2;i<=P;i++)
    for(int j=i;j<=V;j++)
    {
    int mn=MAX;
    for(int k=i-1;k<j;k++)
    {
    if(dp[i-1][k]+d[k+1][j]<mn)
    mn=dp[i-1][k]+d[k+1][j];
    }
    dp[i][j]=mn;
    }
   
    cout<<dp[P][V]<<endl;
    }
return 0;
}

 
原创粉丝点击