华为软件精英挑战赛——图论 最短路径

那个,我不是大佬,以下仅是我的思路、自我反思

一、题目分析

1、官方case图:题目就是在一个容量有限的图内选择安放服务器以满足消费点的流量需求

《华为软件精英挑战赛——图论 最短路径》 官方case图

    初步看到这个示例的时候,内心第一反应就是服务器在一些中间节点,第二反应是服务器会给周边近的消费点提供流量。当然这只是感觉,接下来的问题是: 服务器的数量?服务器位置怎么确定? 怎么选路径供给?  这就是这个题目考察的地方了。

二、算法设计

1、整体是属于“设施选址”问题、可用方法整数规划(虽然我没用,但我相信这是正理)

《华为软件精英挑战赛——图论 最短路径》 我阅读的算法资料

2、启发式算法——迭代搜索(如一些遗传算法、粒子群算法、退火算法,很多大佬使用的)

《华为软件精英挑战赛——图论 最短路径》 大佬的建议  (来源:华为软件精英挑战赛论坛)

3、最小费用流——最小费用最短路径(我的算法仅仅是这样的,缺陷在后面的反思总结)

服务器位置:可用放在流出流量最大的地方 or 到消费点路径上的必经点

服务器数量:我先放了一个在最大流出带宽的地方,然后计算到所有消费点的最短路径,接下来让服务器尽可能的提供给消费点,然后在放一些服务器在必经点times较高的地方,再供给给消费点。最后还有剩下的消费点的话就自己去寻较近的服务器,一个服务器都找不到的话就自己这儿安一个服务器。(ps:安服务器多了成本cost会很高,中间就是要注意服务器安放的位置和数量)、

最小费用流:以单位费用为路径长,广度搜索最短路径(因为这个题的图的关系,这个搜索代码很有趣啊,我在代码实现中展示),找到服务器到每个消费点的最短路径,再求得最小流(路径D[] * flow)

三、代码实现

1、主要函数

《华为软件精英挑战赛——图论 最短路径》 主要函数们~

2、放服务器在流出流量最大的地方后计算它到所有点的Dijkstra,保存路径到D[i]里

《华为软件精英挑战赛——图论 最短路径》 广度遍历搜索最短路径

其实就是在遍历周边全部,依次发散出去,这样就可以很快的找遍全部路径了,收敛还是很快的

《华为软件精英挑战赛——图论 最短路径》

3、处理剩余节点

       while循环处理剩余未满足的消费节点,当消费点出发找不到服务器那么就在这里安放服务器,注意判断之前是否有其他服务器给这里提供了流量,提供了则要归还流量。

《华为软件精英挑战赛——图论 最短路径》 最后处理剩余节点(ans=-1 则要在此处放服务器)

四、Debug

1、一个类里面空间是有限的,如果开了几个1000*1000的二维数组是不行的,要么static,要么设置全局。

2、在Dijkstra 里CountsOfConnectNode不能因为单边减少而减一,因为单边减少就减一的话会造成无法访问一些边,因为我是先遍历的在判断的周边路径是否存在,即weight > 0。

3、一些存DotId的数组我初始化为了-1,其实-1是很容易造成下标越界的,但本来dot的范围是0~maxN,所以造成后面很多的判断 != -1 ,希望大家引以为戒。(因为-1 ,我的graph里的成员变量servercost竟然从100变成了-1,就是因为-1下标的范围导致内存访问异常,数据被修改,当时真是急哭我了)

4、记住所有变量定义的时候一定初始化,否则为任意值的话会造成不可知的错误,只能一直debug一步步找变量的变化,真是心累。

5、如果你的数据很多,请注释每个的含义,包括下标,否则你的队友会看不懂你的代码,自己写一写的就会弄混。

6、最后提交的时候,我发现官方的gcc包是字符串读入、字符串输出,最后一刻在写读入输出,心都紧张的要崩了。还好给力的队友写完了

五、我的成果~

1、最直接的结果,其实实在不想贴判卷情况的图,即是肯定、又是打击。

《华为软件精英挑战赛——图论 最短路径》 结果,哎

      我第三个高级案例崩了,很怪,pathi变量本来是一直递增++的,不知道在while经历了啥,就跳着增然后就crash了,我还在反思。

       我的成果就是我有了自己的思路,自己主要负责写处理算法,一周一共1000+的代码,感谢队友为我排错补坑。其实看到结果路径输出的时候,我激动得狂喊。真的超级有成就感! 但是最后提交了代码后,看到成本真的比较高的时候,内心对整个算法的思路又沉重了~

七、反思总结

1、算法上的缺陷

没有反馈:一直计算的出来的结果,没有经过比较选择这是缺乏了优化的过程的。

我还在想改进:我应该要一直迭代,随机取、放一些服务器后就算一遍最短路径和成本进行比较取优。其实我的代码跑完整个用的时间是ms级的,那么其实还要很多时间可以进行计算。因为最后来不及了也就没有做,自然成本高。

2、团队分工:队友要充分合作(一个人再强大真的比不上三个臭皮匠)、分工写任务,一定要充分相信对方。队长要想好整体,再把模块分开写,把需求明确,免得最后代码合并要哭。

3、编程基本功:编程基本功要多写多练才扎实,不然写这样的复杂稍大的程序就很容易出现一些低级错误

4、多去学习大佬怎么做的,站在前人大佬的基础上才不会自己太犯傻,至少基本的方向不会错!

5、debug一定要心静沉着,心理素质要强,不要急,写一段代码就要测试好。团队也不要互相埋怨,应该要有个好的氛围去解决问题。

6、最后关头一定要保留两份代码,一份是最新的,一份是上次提交的,免得回不去啊

我个人其实一开始是觉得这个很难做的,甚至有点怀疑自己能不能写出来,但是我写出来了我很高兴了。

感谢你看到了这里,希望对你有所帮助~  

《华为软件精英挑战赛——图论 最短路径》 拜拜!比赛,或许我下一年会来

    原文作者:雪之音
    原文地址: https://www.jianshu.com/p/aefc72d03029
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞