接着上一篇的动态规划问题的一道题目:
欧几里德货郎担问题是对平面给定的n个点确定一条连结各点的、闭合的游历路线问题。图1(a)给出了七个点问题的解。Bitonic旅行路线问题是欧几里德货郎担问题的简化,这种旅行路线先从最左边开始,严格地由左至右到最右边的点,然后再严格地由右至左到出发点,求路程最短的路径长度。图1(b)给出了七个点问题的解。
请设计一种多项式时间的算法,解决Bitonic旅行路线问题。
猛地一看似乎没有什么状态可言,但是如果想一下——避免重复计算这样的特点的话——任意两点之间通过点1的最短路线就是一个需要反复计算的问题。
而且这种阶段划分无后效性、有最优子结构、有重叠子问题。
下面为引用分析:
分析:
第一步,先按照每个节点的x坐标进行排序,从左到右标记为1,2,…,n。算法复杂度可以为O(n*log(n))。
第二步, 构建d[i][j]代表从i->1->j的最短路径长度。依据其定义,我们可以知道d[i][j] = d[j][i]。所以我们只计算i>j时的值。(为什么不考虑i==j时的值?因为对于d[n][n]最小的时候,图中必然不存在任意中间节点被走两次。)
构建W[i][j]代表从i到j的直接距离,坐标运算可得。
此时,考虑两种情况:
1 i>j+1时,此时i只可能和i-1节点相连。假设i可以与其它节点直接相连,那么由于i>j,i-1>j,j不可能成为两次路径中任意一次的端点。所以d[i][j] = d[i-1][j] + W[i][i-1]。
2 i==j+1时,此时i可能和所有小于j的节点直接相连。所以
这里为什么不是min(d[i][k]+W[j][k]):因为i>j,d[i][k]已经包含了j点——搞清楚二维数组d的含义.
第三步,初始值d[2][1] = W[2][1],两层循环计算d[i][j]。
for (int i = 3; i <= n; ++i)
for (int j = 1; j < i; ++j)
第四步,计算
所得d[n][n]即为最短双调路线的值。
代码实现比较简单不贴
做完这个题目——动态规划可能需要自己动手去实践一下,看看问题中都需要如何求解,需要的量是什么,哪些量能够当作状态划分的依据。还有就是发现子问题