ccf-csp之地铁修建(最小堆dijkstra算法)

要看题目的思路和代码的直接跳过这一部分。。。

做此题的心路历程

  咳咳,要开始讲了哇,因为我的蜗牛速度(对图的各种算法和基础的C++语法不熟练),所以这道题算是做了两天吧。从昨天上午到今天下午。现在我要正式开讲啦~~
  接到题目,思考了一会儿,我就认为这是一个最短路径的问题(虽然后面查到网上大部分答案都是用最小生成树做的,这是后话~),然后我开始翻严蔚敏老师的《数据结构》,找到图的最短路径这一部分,啊,熟悉的两个算法名字,dijkstra算法和Floyd算法。然鹅,实在是忘了,所以花了可能两三个小时,来温习了这两个算法。之所以花了这么久,是因为我在看dijkstra算法的“正确性证明”这一部分脑子好久都没有拐过弯来(恩,我很认真的,正确性证明都要看的喔~)。让我疑惑不解,怀疑人生的是这段话“假设S为已求得最短路径的终点的集合,则可以证明:下一条最短路径(设其终点为x)或者是弧(v,x),或者是中间只经过S中的顶点而最后达到顶点x的路径。这可以用反证法来证明。假设此路径上有一个顶点不在S中,则说明存在一条终点不在S而长度比此路径短的路径。但是,这是不可能的。因为我们是按路径长度递增的次序来产生各最短路径的,故长度比此路径短的所有路径均已经产生,它们的终点必定在S中,即假设不成立”。(补充说明:v是源点)。关键是对“则说明存在一条终点不在S而长度比此路径短的路径”的理解,这个路径到底是啥,一脸懵x,后来上网查了一下。意思是:设这个不在S中的点为k,则到x的路径可以分为两段(v…..k)+(k….x),那说明到k的路径比到x短嘛,所以说如果选的话,也是k被选上咯,轮不上你x。so….就是个这么玩意儿,脑子卡了有一会儿。
  好,第一个费解点已经过了,下面走在去第二个费解点的路上 o(╥﹏╥)o。比较两种算法,我发现Floyd算法实现起来比较简单,然后就用它实现了交上去,结果好像是运行超时,45分。然后我就改用了dijkstra,当然图的存储结构还用的是二维数组,提交结果是运行错误,50分。就是这个该死的“运行错误”,到昨天晚上出实验室的前十分钟,我都没有弄明白为什么是运行错误。卡壳一下午。一度怀疑这个问题能不能用最短路径算法来求解。然后套用上面的正确性证明,到x的路径可以分为(v…..k)和(k….x),那么dis[x]’=Max(dis[x],dis[k]’,Max(k…x)) ,dis[x]’为v到x新的最短距离(此题中“最短距离”的含义为:一条路径上,所有段中天数的最大值),dis[x]是之前的,dis[k]’是(v…..k)段上最短距离,Max(k…x)指的是k到x所有段中的最大的那个数值。如果只考虑经过k的这条路径的话,那么结果得到的dis[x]会大于等于dis[k]。问题就出现在这个“等于”上, 既然k点的数值和x点的可能相等,那么选择的时候也可能选k点,而不是x点。仔细考虑下,这个“等于”的情况对最后结果应该也没有影响的,只能说明到目标点有两条或者多条长度相等的最短路径(以上证明我今天才想清楚了些,昨天还是糊涂的)。百度了下,虽然大多数人用的是最小生成树,但是也有用dijkstra做出来的,所以我放心地陷进了这个算法,思考着为啥我的dijkstra为啥就不行┭┮﹏┭┮。。。终于昨天晚上出实验室之前,灵光一现,发现很有可能是因为用的数据结构是二维数组,占内存太大。因为我看我的提交结果所占内存是256.8M,但是要求的是256M,因为天色已晚,我要保证自己的规律作息,所以回去了,打算今天一早回来试一下,当然回去了之后还是满脑子的正确性证明,翻来覆去。。。啊啊,归根结底,为啥你要提示“运行错误”啊,你提示“超出内存”不简单明了多了。。
  好了,时间终于到了今天,开始跳第三个坑ヘ(;´Д`ヘ)。一早上试了一下用邻接表(Adjacency List)来存储图结构,然而本地VS2013运行毫无问题,提交上去,秒回“编译错误”。各种百度,后来发现问题在于没有#include<malloc.h> 而且,

struct ArcNode{
    int adjvex;
    ArcNode *NextArc;
      };

在VS里完全可以,然而到dev-c++编译器里面就会报错,应该写成这样

struct ArcNode{
    int adjvex;
    Struct ArcNode *NextArc;
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值