《DSAA》 10.5.1 收费公路重建问题

收费公路重建问题得名于对美国西海岸公路上那些收税公路出口的模拟:设一条高速公路从起点到终点之间有若干出入口(包括起点和终点),每个出入口设有一个收费站,每两个出入口的距离已知,收费站根据这些距离收费。某天不知发生了什么灾难,这些出入口及其收费站居然消失了,只有起点和各点之间的距离保存下来,现在要重建收费站,则需要求出这些出入口的位置。也就是说要根据距离的集合 D[ ],反过来求出点的集合 X[ ]。

我们知道如果一个无向连通图的顶点数为N,那么其边数则为 N × (N - 1) / 2,所以首先可以求出 X[ ] 中点的数目。

开始的3个点比较简单,设起点坐标X[1] = 0,那么加上最大的距离可得到终点 X[N],然后再根据第二大的距离可得到 X[N - 1](或者是 X[2],这两个可任选一个,因为互为镜像,所以是等价的)。但之后的情形就变得不确定了,所以从这里开始采用回溯算法递归求解:每次我们传递同样的参数及界 Left 和 Right,X[Left] ... X[Right] 是未知的点,这个界之外的点为已知点,如果 D[ ] 是空集,则解已找到,那么返回。否则首先尝试 X[Right] = D[Max],如果其与所有已知点的距离都在 D[ ]中出现,那么试着放入这一点,同时从 D[ ]中删除这些距离,进入下一轮尝试即 X[Left] ... X[Right - 1],如果这些距离对不上,或下一轮尝试出错,那么恢复 D[ ],在相反方向上用同样方法再尝试 X[Left] = X[N] - D[Max]。忽然觉得这个算法有点像西方的选举:右派先上来试试,干一段如果不行,推倒重来换左派再上来试试。

实现时主要遇到的问题是一个特定的距离值在 D[ ] 中可能出现不止一次,针对这个问题:

1)可以用一颗二叉查找树实现 D[ ],但该二叉树必须支持对元素的重复插入

2)检查D[ ]中距离的时候不仅要核对距离的值,还要核对该距离出现的次数

下面是对原书中示例的求解,运行结果如下 (前面显示的是二叉树,后面是回溯算法过程):




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值