首页 > 代码库 > poj1160 Post Office 四边形不等式
poj1160 Post Office 四边形不等式
在一条直线上有n个村庄,选出m个村庄,在其中每个村庄建立一个邮局,要求每个村庄到最近邮局的距离和最小。
f[i][j]:在前i个村庄中建立j个邮局的最小耗费
dis[i][j]:在第i个村庄到第j个村庄中建立1个邮局的最小耗费
那么就有转移方程:f[i][j] = min(f[i][j],f[k][j-1]+dis[k+1][i]) DP的边界状态即为f[i][1] = dis[1][i]; 所要求的结果即为f[n][m];
然后就说说求dis数组的优化问题,可以假定有6个村庄,村庄的坐标已知分别为p1,p2,p3,p4,p5,p6;那么,如果要求dis[1][4]的话邮局需要建立在2或者3处,
放在2处的消耗为p4-p2+p3-p2+p2-p1=p4-p2+p3-p1
放在3处的结果为p4-p3+p3-p2+p3-p1=p4+p3-p2-p1,
可见,将邮局建在2处或3处是一样的。现在接着求sum[1][5],现在处于中点的村庄是3,那么1-4到3的距离和刚才已经求出了,即为dis[1][4],所以只需再加上5到3的距离即可。
同样,求dis[1][6]的时候也可以用dis[1][5]加上6到中点的距离。
所以有递推关系:dis[i][j] = dis[i][j-1] + p[j] -p[(i+j)/2]
用四边形不等式优化了一下
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define N 1000 #define INF 100000000 using namespace std; int n,m,i,j,k,p[N],dis[N][N],f[N][N],s[N][N]; void Init() //初始化 { for (i=1; i<=n; i++) for (j=1; j<=n; j++) f[i][j]=INF; for (i=1; i<=n; i++) f[i][1]=dis[1][i]; for (i=1; i<=m; i++) s[n + 1][i]=n; } int main() { scanf("%d%d",&n,&m); for (i=1; i<=n; i++) scanf("%d",&p[i]); for (i=1; i<=n; i++) for (j=i+1; j<=n; j++) dis[i][j]=dis[i][j - 1] + p[j] - p[(i + j) >> 1]; Init(); for (j=2; j<=m; j++) for (i=n; i>j; i--) for (k=s[i][j - 1]; k<=s[i + 1][j]; k++) { int t=f[k][j - 1] + dis[k + 1][i]; if (f[i][j] > t) { f[i][j]=t; s[i][j]=k; } } printf("%d",f[n][m]); return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。