欧几里得旅行商问题是指:对于给定平面上的n个点,确定一条连接各点的、闭合的最短曲线这个问题是NP完全问题。Bitonic旅行路线问题是欧几里得旅行商问题的简化,这种旅行路线从最左边开始,严格地由左至右到最右边的点,然后再严格的由右至左回到开始点,求最短的路径长度。设计一个确定最优Bitonic旅行路线的O(n2 )时间算法。假设不存在x坐标相同的点。
根据题意,首先将给定的n个点{p1 ,p2 ,…,pn }按x坐标的升序排列。在这里,我采用了快速排序算法,时间复杂度为O(nlogn)。对排好序的n个点进行分析很容易知道p1 是最左侧的点,pn 是最右侧的点。
下面刻画最优解的结构:首先定义路径Pi,j (i<=j),对于路径Pi,j 来说,它包含的点为p1 ,p2 ,..pj 。其中pi 点为起始点,pi,j 表示从pi 点开始走,一直向左走到p1 然后从p1 点沿不同的路径向右走直到pj 。其次,定义数组d[i,j]表示pi,j 路径上的最小Bitonic路线。很容易看出,题目所求的即是d[n,n]。题目的最优解为d[n,n],此时,分析当pn 点未连通的情况。因为点是排好序的,而且根据题意中的严格方向的要求,可以知道pn 点必有一侧是跟pn-1 点相连的,那么此时d[n-1,n]应该为pn-1,n 的最优解。采用反证法,如果存在d’[n-1,n]<d[n-1,n],那么用d’[n-1,n]来替换d[n-1,n]就可以得到一个更小的d[n,n],与已知d[n,n]为最优解矛盾,因此假设不成立。
刻画好了最优解的结构,下面递归定义求解最优解的值:当只有一个点时,d[1,1]无意义。分析大于等于两个点的情况:当只有两个点时,很容易得到:d[1,2]=|p1 p2 |。对于路径Pi,j 来说,如果pi 不是pj 的相邻点(i=j-1),d[i,j]=d[i,j-1]+|pj-1 pj |;当i=j-1时,对于pj 点来说,有一侧必与pi 点相连,此时要判断pj 点的另一侧与哪个点相连。根据最优解的结构,此时,定义整数k(1<=k<j-1),计算每个d[k,j-1]+|pk pj |的值,选择其中最小的一个作为d[i,j]的值,并且记录k值,将pj 与pk 相连。
根据以上分析,可以得到d[n,n]的计算方法如下所示:
d[1,2]=|p1 p2 |
d[i,j]=d[i,j-1]+|pj-1 pj |(i<j-1)
d[i,j]=min1<=k<j-1 {d[k,j-1]+|pk pj |}
d[n,n]=d[n-1,n]+|pn-1 pn |
接下来计算最优解的值,采用自底向上方法,在计算过程中,需要保存两个值,第一个是数组d[i,j]的值,第二个是要记录pi,j 中pj 点的相邻连接点的下标,用数组pre[i,j]表示。算法如下所示:
Bitonic-tour(p)
Quicksort{p1 ,p2 ,…pn } in order of increasing x-coordinate
d[1,2]←|p1 p2 |
for j←3 to n
do for i←1 to j-2
do d[i,j] ← d[i,j-1]+|pj-1 pj |
pre[i,j]=j-1
d[j-1,j] ← ∞
for k←1 to j-2
do a←b[k,j-1]+|pk pj |
if a<d[j-1,j]
then d[j-1,j] ←a
pre[j-1,j] ←k
d[n,n]=d[n-1,n]+|pn-1 pn |
return d and pre
最后,构造问题的最优解:根据题意,题目应该输出一个关于点集p的序列,这个序列即是题目中所求的旅游路线。在这里,我定义了输出的方式为从最右侧的点pn 开始输出,依次输出左行方向的点直到p1 ,然后输出右行方向的点直到和pn 相连的那个点为止。我们已知两个表d[i,j]和pre[i,j],输出的算法描述如下所示:
Output-tour(p)
print pn
print pn-1
k←pre[n-1,n]
Print-tour(pre,k,n-1)
print pk
Print-tour(pre,i,j)
if i<j
then k←pre[i,j]
print pk
if k>1
then Print-tour(pre,i,k)
else k←pre[j,i]
if k>1
then Print-tour(pre,k,j)
print pk
关键点的理解:就是排序后p1,...,pn-1,pn 这n个点,组成的最优解中,由于要求是双调,所以pn一
定与pn-1这个点向连。所以就可以把一个求环的问题归约成一个求简单路径的问题。
这个简单路径就是pn-1严格递减向左走到p1,然后p1在严格递增向右走到pn.这个路径恰好用到p1到pn这n个 点。求解思想就是动态规划。