【POJ1160】【IOI2000】邮局(区间dp)
2017-03-10 22:21
253 查看
【题目描述】
有一条笔直的高速公路,路旁分布着一些村庄。公路可以用一条数轴表示,则村庄的位置就是其坐标。没有两个村庄的坐标相同。两个村庄之间的距离就是它们坐标之差的绝对值。
一些——但不一定是所有的村庄将修建邮局。邮局和该邮局所在的村庄处于同一位置。应当仔细选择邮局的位置,使得所有村庄到最近邮局的距离总和最短。
你要编写一个程序,给出所有村庄的坐标和计划修建的邮局个数,计算所有村庄到最近邮局的距离总和的最小可能值。
【输入格式】
输入文件的第一行有2个正整数:村庄数V(1<=V<=300),邮局数P(1<=P<=30),P<=V。
第二行有V个正整数,分别代表N个村庄的坐标。坐标的范围是[1,10000],坐标按递增顺序给出。
【输出格式】
输出一行一个正整数S,即所有村庄到最近邮局的距离总和的最小可能值。
【样例输入】
10 5
1 2 3 6 7 9 11 22 44 50
【样例输出】
9
【提示】
对于30%的数据,1<=P<=N<=10.
对于100%的数据,1<=P<=30,1<=N<=300,P<=N.
【题解】
本题不太好想,我们可以本着特殊到一般的思想,先考虑村庄i到村庄j之间只有一个邮局的情况。那么这个邮局就一定在i和j的中点处。
令dis[i][j]表示i到j之间只有一个邮局时的距离和,则
dis[i][j]=dis[i][j-1]+pos[j]-poj[(i+j)>>1];
下面我们来考虑多个邮局的情况,同样可有递推式:令dp[i][j]表示前i个村庄建了j个邮局的距离最小和,则
dp[i][j]=dp
4000
[k][j-1]+dis[k+1][i]; (j-1 <= k < i)
有点类似C(N,M)=C(N-1,M)+C(N-1,m-1)吧?
其实就是前k个村庄修了j-1个邮局,后面再修一个的最小值。
边界情况:
dp[i][i]=0//每村一个
dp[i][1]=dis[1][i]//只有一个
代码如下:
P.S.感觉POJ有毒,COGS上1Y,POJ上一直都是RE……
有一条笔直的高速公路,路旁分布着一些村庄。公路可以用一条数轴表示,则村庄的位置就是其坐标。没有两个村庄的坐标相同。两个村庄之间的距离就是它们坐标之差的绝对值。
一些——但不一定是所有的村庄将修建邮局。邮局和该邮局所在的村庄处于同一位置。应当仔细选择邮局的位置,使得所有村庄到最近邮局的距离总和最短。
你要编写一个程序,给出所有村庄的坐标和计划修建的邮局个数,计算所有村庄到最近邮局的距离总和的最小可能值。
【输入格式】
输入文件的第一行有2个正整数:村庄数V(1<=V<=300),邮局数P(1<=P<=30),P<=V。
第二行有V个正整数,分别代表N个村庄的坐标。坐标的范围是[1,10000],坐标按递增顺序给出。
【输出格式】
输出一行一个正整数S,即所有村庄到最近邮局的距离总和的最小可能值。
【样例输入】
10 5
1 2 3 6 7 9 11 22 44 50
【样例输出】
9
【提示】
对于30%的数据,1<=P<=N<=10.
对于100%的数据,1<=P<=30,1<=N<=300,P<=N.
【题解】
本题不太好想,我们可以本着特殊到一般的思想,先考虑村庄i到村庄j之间只有一个邮局的情况。那么这个邮局就一定在i和j的中点处。
令dis[i][j]表示i到j之间只有一个邮局时的距离和,则
dis[i][j]=dis[i][j-1]+pos[j]-poj[(i+j)>>1];
下面我们来考虑多个邮局的情况,同样可有递推式:令dp[i][j]表示前i个村庄建了j个邮局的距离最小和,则
dp[i][j]=dp
4000
[k][j-1]+dis[k+1][i]; (j-1 <= k < i)
有点类似C(N,M)=C(N-1,M)+C(N-1,m-1)吧?
其实就是前k个村庄修了j-1个邮局,后面再修一个的最小值。
边界情况:
dp[i][i]=0//每村一个
dp[i][1]=dis[1][i]//只有一个
代码如下:
#include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #define ll long long #define inf 0x7f7f7f7f #define N 305 #define M 35 using namespace std; int n,m,x ,dis ,dp [M]; int main() { freopen("postoffice.in","r",stdin); freopen("postoffice.out","w",stdout); while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%d",&x[i]); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2]; for(int i=1;i<=n;i++) { dp[i][i]=0; dp[i][1]=dis[1][i]; } for(int j=2;j<=m;j++) for(int i=j+1;i<=n;i++) { dp[i][j]=inf; for(int k=j-1;k<i;k++) dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]); } printf("%d\n",dp [m]); } return 0; }
P.S.感觉POJ有毒,COGS上1Y,POJ上一直都是RE……
相关文章推荐
- POJ 1160 经典区间dp/四边形优化
- poj 1160 Post Office (区间DP)
- poj1160(区间DP)
- DP 【POJ1160】POST OFFICE 邮局问题
- ioi2000 poj 1160 VIJOS-P1242 邮局问题
- POJ 1160 (区间DP+四边形优化)
- POJ 1160:Post Office 邮局经典DP
- POJ 1160 Post Office(区间DP)
- POJ 1160 Post Office (区间DP+重心)
- POJ 1160 普通区间DP||四边形优化DP
- POJ 1160:Post Office 邮局经典DP
- POJ 1160 区间DP + 平行四边形优化
- 【区间DP】POJ_3186_Treats for the Cows
- POJ 1160 Post Office(经典DP)
- poj 2955 Brackets(括号匹配,区间DP)
- POJ 1651 区间DP Multiplication Puzzle
- POJ 3280 Cheapest Palindrome(区间dp)
- POJ 2955 Brackets (区间dp)
- poj 1141 Brackets Sequence(区间DP->括号匹配的最优生成)
- POJ 3616 Milking Time 挤奶问题,带权区间DP