您的位置:首页 > 其它

poj 1160 Post Office //四边形不等式优化

2011-03-02 12:19 155 查看
http://blog.csdn.net/find_my_dream/archive/2009/12/03/4931222.aspx

这个博客概括的比较好

 

四边形不等式优化------邮局问题

 

m[p,n]为问题的解

m[i,j]表示在前j个村庄建立i个邮局的最小距离和

 

状态转移方程和边界条件是

m[1,j]=w[1,j]

m[i,j]=min(m[i-1,k]+w[k+1,j])  i<=j

 

其中w[i,j]表示在d[i..j]之间建立一个邮局的最小距离和,

可以证明,当仅建立一个邮局时,最优解出现在中位数,

即设建立邮局的村庄为k,则k=(i+j)/2

计算w[i,j]是比较简单的,不作阐述

 

同时令s[i,j]=k,记录使用前i-1个邮局的村庄数

便于在算出最小距离和之后构造最优建立方案。

 

上述算法中w[i,j]可通过O(n)时间的预处理,在O(1)的时间内算出,

所以,该算法的状态总数为O(n*p),每个状态转移的状态数为O(n),

每次状态转移的时间为O(1),该算法总的时间复杂度为O(p*n^2)。

 

 

以下就是算法的优化

首先这个题目的状态转移方程让我猜测它是否也满足单调性

即  s[i-1,j]<=s[i,j]<=s[i,j+1]

 

首先我们证明函数w满足四边形不等式,即

w[i,j]+w[i',j']<=w[i',j]+w[i,j'] , i<=i'<=j<=j'

设y=(i'+j)/2  z=(i+j')/2

下面可分两种情形讨论,z<=y和z>y,不过这两种情形相似

证明可参考毛子青大牛的论文,不作阐述

 

再用数学归纳法证明m函数也满足四边形不等式,

 

最后,我们证明决策s[i,j]满足单调性。

为讨论方便,令mk[i,j]=m[i-1,k]+w[k+1,j];

我们先来证明s[i-1,j]≤s[i,j],

只要证明对于所有i≤k<k'<j且mk'[i-1,j]≤mk[i-1,j],

有:mk'[i,j]≤mk[i,j]。

 

类似地,我们可以证明一个更强的不等式

mk[i-1,j]-mk'[i-1,j]≤mk[i,j]-mk'[i,j]

也就是:mk[i-1,j]+mk'[i,j]≤mk[i,j]+mk'[i-1,j]

利用递推定义式展开整理的:m[i-2,k]+m[i-1,k']≤m[i-1,k]+m[i-2,k'],

这就是i-2<i-1<k<k'时m的四边形不等式。

我们再来证明s[i,j]≤s[i,j+1],

与上文类似,设k<k'<j,则我们只需证明一个更强的不等式:             

mk[i,j]-mk'[i,j]≤mk[i,j+1]-mk'[i,j+1]

也就是:mk[i,j]+mk'[i,j+1]≤mk[i,j+1]+mk'[i,j]

 

利用递推定义式展开整理的:

w[k+1,j]+w[k'+1,j+1]≤w[k+1,j+1]+w[k'+1,j],

这就是k+1<k'+1<j<j+1时w的四边形不等式。

综上所述,该问题的决策s[i,j]具有单调性,

 

m[1,j]=w[1,j]

m[i,j]=min(m[i-1,k]+w[k+1,j])  i<=j

s[i,j]=k

 

同上文所述,优化后的算法时间复杂度为O(n*p)。

 

 

#include<cstdio>
#define inf 0x7ffffff
int dp[301][31];//dp[i][j]表示前i个村庄放j个邮局的最短距离
int w[301][301];//w[i][j]表示[i,j]的最小距离
int val[301];
int s[301][31];//s[i][j]记录前j-1个邮局的村庄数
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1 ;i<=n ;i++) //这里有一个递推公式可以进行预处理
{
w[i][i]=0;
for(int j=i+1;j<=n;j++)
w[i][j]=w[i][j-1]+val[j]-val[(j + i)/2];
}
for(int i=1;i<=n;i++)
{
dp[i][1]=w[1][i];
s[i][1]=0;
}
//for(int i=1;i<=m;i++) s[n+1][i]=n;
for(int i=2;i<=m;i++)
{
s[n+1][i]=n;//s[][]上限的初始化
for(int j=n;j>i;j--)//决策量s[i][j]已经是缩短了搜索的范围
{
dp[j][i]=inf;
/*在s[i-1][j]到s[i][j+1]的范围内枚举k值,
计算前k个村庄建立一个i-1个邮局、第k+1个村庄~第j个村庄建立一个
邮局的距离和.若该距离为目前最小,则记下方案.*/
for(int k=s[j][i-1];k<=s[j+1][i];k++)
{
int tmp=dp[k][i-1]+w[k+1][j];
if(tmp<dp[j][i])
{
dp[j][i]=tmp;
s[j][i]=k;
}
}
}
}
printf("%d/n",dp
[m]);
}
return 0;
}
 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  office 算法 优化