poj1160 Post Office

来源:互联网 发布:centos 6.7 升级内核 编辑:程序博客网 时间:2024/04/28 22:27

点击打开链接 DP

题意:有V(1<=V<=300)个村庄在x轴上,给出横坐标,有P(1<=P<=30,P<=V)个邮局要建在这些村庄里,每个村庄至多建一个,问怎样建使得每个村庄到最近的邮局的距离之和最短。

分析:这种题毫无疑问是DP,难点在于如何动态转移,考虑到如果两个邮局已建好,这两个邮局之间的村庄总距离也就确定了,dp[i][j]表示在前i个村庄建j个邮局*且第j个邮局建在第i个村庄,那么d[i][j]=min(d[k][j-1]+cost[k][j]),cost[i][j]为在i,j建邮局,村庄i-j到最近邮局距离之和。

#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<iomanip>#include<map>#include<algorithm>#include<queue>#include<set>#define inf 100000000#define PI acos(-1.0)#define eps 1e-8#define seed 131using namespace std;typedef unsigned long long ULL;typedef long long LL;typedef pair<int,int> pii;const int maxn=100005;int v,p;int m[305];int d[305][35];int cost[305][305];int main(){    scanf("%d%d",&v,&p);    for(int i=1;i<=v;i++)        scanf("%d",&m[i]);    for(int i=1;i<=v;i++)        for(int j=1;j<=p;j++)        d[i][j]=inf;    d[1][1]=0;    for(int i=2;i<=v;i++)    {        int ans=0;        for(int j=1;j<i;j++)            ans+=m[i]-m[j];        d[i][1]=ans;    }    for(int i=1;i<=v;i++)    {        for(int j=1;j<=v;j++)        {            int ans=0;            for(int k=i+1;k<j;k++)            {                ans+=min(m[k]-m[i],m[j]-m[k]);            }            cost[i][j]=ans;        }    }    for(int i=1;i<=v;i++)    {        for(int j=2;j<=p;j++)        {            if(i<j)                continue;            for(int k=j-1;k<i;k++)                d[i][j]=min(d[i][j],d[k][j-1]+cost[k][i]);        }    }    int tot=inf;    for(int i=p;i<=v;i++)    {        int u=d[i][p];        for(int j=i+1;j<=v;j++)            u+=m[j]-m[i];        tot=min(tot,u);    }    cout<<tot<<endl;    return 0;}


0 0