2019中兴迪杰斯特拉比赛回顾与分析
1.赛题信息
已知条件:
1) 有一网格状拓扑(25*20,数据见gridtopo.txt),现在需要组建长期运输网;拓扑中链路的最大容量(最大承受带宽)已知;链路的单位质量业务的传输成本已知;
2) 有1000种蚁穴到蚁穴(源节点到终节点)的业务需要运输,每种业务的质量(带宽)已知;
3) 蚁巢王国在最初建立之时,城市规划师为每两个蚁穴之间规划了3条备选通道,用于蚁穴之间互访。即每种业务有3条备用通道供业务传输(每条路径由多段链路组成的,数据见request.txt),可是,随着时代的变迁,这些备选通道可能会存在不合理的地方,于是在业务传输的时候,小蚁们可以自己决定是否要选择合适的路径计算算法来计算新的路径进行传输,并不需要局限于当前的3条路径;
4 ) 每种业务需要从自己的备选通道(路径)或者新计算出的路径中选出一条有效路径完成业务传输,且该业务的传输成本可定义为:业务质量*路径传输单位质量业务成本,后者的定义为:路径上面包含的所有链路的单位质量业务的传输成本之和;
5 ) 每条链路被业务占用的容量(带宽)之和不能超过该链路的最大承受带宽的80%。
特别说明
1)同一条链路认为是双向的,即存在A->B和B->A两个方向,且互不影响,它们有各自的链路带宽,并假定带宽值相同;
2)两个网络节点之间最多仅存在一条链路,链路上下行方向的带宽相互独立互不影响且相同。例如对于节点A与B之间的链路,该条链路的带宽为1G,则表示A->B,B->A两个方向上的网络带宽分别为1G。
待解决问题:
如何从全局角度考虑,给每种业务选择一条通道(路径),在满足所有链路传输带宽要求(不超过80%)的情况下,使得1000种业务总的传输成本之和最小?(具体见下文评分机制).
2.程序输入与输出
网络拓扑如图所示:
输入文件示例:
- gridtopo.txt(网络拓扑数据)
4 5 //注:4个网络节点,5条链路
0 1 10 10 //注:链路起始网络节点ID为0,链路终止网络节点为1,最大承受带宽为10,单位质量业务传输成本为10
0 2 10 10
1 3 10 10
1 2 10 10
2 3 10 10
2 request.txt(业务请求数据)
2 2 //一共2种业务,每中业务2条备用路径
0 1 //业务请求ID 为0,请求带宽1
0 1 3 //备用路径
0 2 3 //备用路径
1 3 //业务请求ID为1,请求带宽3
1 2 3 //备用路径
1 3 //备用路径
输出文件示例
输出文件为txt文件,命名result.txt;txt文件每行内以空格分隔,文件每行以换行符结尾
1)如果不存在满足条件的传输方案,则输出一行
NA
(文件结束)
- 如果存在满足条件的方案,则按如下格式输出
总的传输成本
业务ID 请求带宽
路径节点列表//(节点列表中间以空格分隔,如A B C)
.....................(若干行)
(文件结束)
- 输出示例
80 //总的传输成本为80
0 1 //业务请求ID为0,请求带宽为r1
0 1 3 //选择路径
1 3 //业务请求id为1,请求带宽为r2
1 2 3 //选择路径
特别说明:
- 输出路径按照业务id从小到大输出。
- 业务大小数据必须与输入文件中数据相吻合,且业务的路径也要符合要求,否则视为无效结果。
分析
本次比赛时间精力有限,采用的算法简单,成绩不是很理想。
先来简单分析一下题目,本次比赛在一张拓扑图中,需要满足带宽的限制,为每一个请求安排一条路径连接起点到终点,计算出该路径成本,寻找总成本最优的结果。
首先,刚开始被比赛方带偏了,比赛方给出的请求的参考路径其实没什么用,仅仅使用这些路径数据分配,测试用例的总成本较优解也就500多w。
要想有效的降低成本结果,需要摒弃输入中提供的路径,所有路径都由自己去分配。
首先我想到的可能是用迪杰斯特拉算法等,逐一的找寻最优路径,再交换顺序重新分配。
又或者是每次随机的选择路径,分配完成后,再随机的对一条路径进行优化,最后一点一点的逼近最优解。
但是经过测试之后,发现效果都不好。因为比赛要求1分钟完成计算解题,而搜索路径是极为耗时的操作,因而收敛慢,效果差。
采用的策略
经过多次尝试,我采用的策略如下:
1.首先不考虑带宽限制,运行一次Floyd计算各个请求的最短成本路径。
2.调整路径放置顺序,将路径按成本从小到大的先后顺序放入网络中,如果请求路径带宽超出限制,则不放。
3. 将所有能放下的放入后,对于剩余的请求,按照第一次的floyd路径的初始拟放置路径成本从小到大的顺序,依次计算迪杰斯特拉最短成本路径,并放入网络中,更新网络(主要是剩余带宽信息),继续布置下一个,直到最终所有请求都完成布置。
该方法测试用例能达到412w。该方法简单快捷,限制1分钟,实际只用了5秒左右,不具备自动调优的能力,对于同一输入,结果都是一致的。后面会讲讲优秀的同学的方法。其实对于规划路径排序依据我试了几个评判标准,比如路径的总带宽啊,最大边带宽啊,路径的边带宽与成本之比等等,最后发现还是根据成本排序效果最好。
代码实现
main函数
public static void main(String[] args) throws IOException, CloneNotSupportedException {// LogUtil.printLog("Begin");String girdPath = "D:\\资料\\中兴比赛\\迪杰斯特拉\\case1\\gridtopo.txt";String reqPath = "D:\\资料\\中兴比赛\\迪杰斯特拉\\case1\\request.txt";String address = "D:\\downloads\\1-迪杰斯特拉-网络均衡流量\\测试数据-对外公布\\case\\gridtopoAndRequest.txt";String resPath = "D:\\downloads\\1-迪杰斯特拉-网络均衡流量\\测试数据-对外公布\\case\\结果1.txt";
// String[] grid = FileUtil.read(girdPath, null);
// String[] req = FileUtil.read(reqPath, null);String[] input = FileUtil.read(address, null);
// String[] input = readText();/*=============================处理Gridtopo.txt=================================== */int totalNodeNum = Integer.parseInt(input[0].split(" ")[0]);int totalPathNum = Integer.parseInt(input[0].split(" ")[1]);int[][] RequestIdFromStart2End = new int[totalPathNum][totalPathNum];//起点到终点信息记录
// System.out.println(totalNodeNum+","+totalPathNum);GridTopo topo = new GridTopo(totalNodeNum,totalPathNum);topo.populateFrom(input);/*=============================处理request.txt=================================== */RequestInfos requestInfos = poputateRequestInfos(input,totalPathNum);/** computeMiniPathGroup方法*/Floyd floyd = new Floyd(topo,requestInfos.getRequests());
// Floyd floyd = new Floyd(topo.getCosts(),topo.getTotalBWs(),new String[totalNodeNum][totalNodeNum],
// requestInfos.getRequests(),RequestIdFromStart2End);floyd.computeMiniPathGroup();
// System.out.println(requestInfos.getRequests().get(0).getMinPath());floyd=null;//释放内存/*=============================分配=================================== *//** 顺序先放小后放大*/QuickSort qs = new QuickSort(requestInfos.getRequests());qs.sortCost(0, requestInfos.getRequests().size()-1);//快排,属性值带宽System.out.println();int costSum = Assign.assign(requestInfos,topo);RequestInfos resRequestInfos = requestInfos;int finalCostSum = costSum;// System.out.println("全网最小成本:"+costSum);//String[] result = new String[resRequestInfos.getTotalRequestNum()*2+1];result[0] = String.valueOf(finalCostSum);populateResult(result,resRequestInfos);
// int index1 = 1;/*============================输出结果=======================================*/// for(String s:result){
// System.out.println(s);
// }System.out.println(finalCostSum);FileUtil.write(resPath, result, false);
// LogUtil.printLog("End");}
Floyd方法计算最短路径和按照路径成本进行快排采用的是网上的经典模板改写的,这里就不再赘述。
说一下放置的实现。
public static int planPaths(RequestInfos requestInfos, GridTopo topo) {int[][] leftBW = copyof(topo.getTotalBWs());allPathCostSum = 0;ArrayList<Request> failRequests = startPlaceFloydPath(requestInfos,leftBW);System.out.println(failRequests.size());planPathForRemainingRequests(failRequests,topo,leftBW);return allPathCostSum;}
private static ArrayList<Request> startPlaceFloydPath(RequestInfos requestInfos, int[][] leftBW) {ArrayList<Request> failRequest = new ArrayList<>();for(int i=0;i<requestInfos.getRequests().size();i++){Request req = requestInfos.getRequests().get(i);int reqBW = req.getReqBW();
// System.out.print(reqBW+",");if(tryToPlaceAFloydPath(reqBW, req.getMinPath(), leftBW)){ //成功allPathCostSum += req.getMinPathTotalCost()*req.getReqBW();}else{ //失败,添加失败位置failRequest.add(req);
// System.out.println(req.id);}}return failRequest;}
private static void planPathForRemainingRequests(ArrayList<Request> failRequests, GridTopo topo, int[][] leftBW) {for(int i=0;i<failRequests.size();i++){
// int ii = failPoi.get(i);
// Request request = requestInfos.getRequests().get(ii);Request request = failRequests.get(i);int reqBW = request.getReqBW();//适用于该请求的cost,将带宽不足的链路cost设置为infint[][] tempCost = refreshTopoCostInfos(topo.getCosts(),leftBW,reqBW);//包含路径和距离String[] res = Dijkstra.Dijsktra(tempCost, request.getStart(), request.getEnd()).split(" ");int[] path = new int[res.length-1];//0~n-1位是路径for(int j=0;j<res.length-1;j++){path[j] = Integer.parseInt(res[j]);}request.setMinPath(path);//最后一位是距离即单位成本int totalCostofAPath = Integer.parseInt(res[res.length-1]);request.setMinPathTotalCost(totalCostofAPath);//更新总成本和剩余带宽placePath(reqBW, path, leftBW);allPathCostSum += totalCostofAPath*reqBW;}}
接下来就可以按照格式,输出result文件了。
总结和反思
本次比赛,恰逢写毕业论文的繁忙期,所以最后很遗憾没有进入30强,但是赛后听取了大佬们的清奇思路。这里说两个排名比较厉害的选手的解题办法。
1. 排第一位的选手,选择首先在不考虑带宽限制的条件下,计算出各个请求的最短floyd成本路径(这一步跟我一样有木有!),然后根据网络中边的带宽分部情况,调节带宽超负载的边的成本值(此成本只用于规划路径,计算总成本是使用真实路径成本),成本值改变,那相应的计算出的最短路径就会改变。调节一个边的成本可能会使得许多条请求的最短路径改变。该大佬说样例,20次能收敛到比较好的解,真厉害。
这位选手说的是仅仅重新计算最短成本路径中包含带宽超负载的请求的路径【集合A】(我也觉得是这样,因为如果全部重新计算路径,1分钟内很难收敛,一分钟最多计算30-50次floyd左右)。
这里有一个问题是,到下一轮,A中重新规划的路径,必然会与其他的路径抢夺带宽资源,形成新的超负载带宽边,因此下一次重新规划路径是只重新计算上一次的分配路径集合A中剩余的仍然超带宽的请求,还是说将包含新的超带宽边的请求路径也添加进来,重新计算路径 。
另外,这个思路的关键之处是怎样根据一条边的带宽的过载程度来相应的增加成本以达到调节网络负载的目的,如何随着循环次数的增加动态的调节这个过程,使得最终收敛一个较好的结果。我尝试了一下,样例输入是430w多,不容易收敛,循环次数多了,反而结果变差,很难复刻他的效果。
2. 另一个高分选手的思路是,使用dijkstra为每一个请求依次分配最短路径。然后随机取出几个请求的路径,重新计算再填入,多次重复前面取出,重新分配的过程,逼近最优解。
资源下载
最后附上完整的程序下载链接,欢迎下载。
https://download.csdn.net/download/mtngt11/11647394
2019中兴迪杰斯特拉比赛回顾与分析相关推荐
- 利用迪杰斯特拉算法求某一顶点到其余各顶点的最短路径
[迪杰斯特拉算法思想] 设有两个顶点集合S和T,集合S中存放图中已找到最短路径的顶点,集合T存放图中剩余顶点.初始状态下,集合S中只包含源点V0.然后不断从集合T中选取到顶点V0路径长度最短的顶点Vu ...
- 2020中兴捧月算法精英挑战赛-迪杰斯特拉派初赛(未来城市物流系统)总结
疫情关系,导致科研一直没法开展,老板着急,自己也无所事事.在清明过后看到了中兴的算法精英挑战赛,然后就开始了算法之旅,这里自己做一点总结,为自己以后争取点教训吧. 数据分析的重要性 这次比赛真的让我体 ...
- 第一届中兴捧月算法大赛迪杰斯特拉派解决方案
迪杰斯特拉派初赛赛题 最强大脑中的收官蜂巢迷宫变态级挑战,相信大家都叹为观止!最强大脑收官战打响后,收视率节节攀升,就连蚁后也不时出题难为一下她的子民们.在动物世界中,称得上活地图的,除了蜜蜂,蚂蚁当 ...
- java迪杰斯特拉算法_迪杰斯特拉算法完整代码(Java)
package com.rao.graph; import java.util.*; /** * @author Srao * @className Dijkstra * @date 2019/12/ ...
- 迪杰斯特拉算法 两点间最短路径的选择
百度首页 登录 注册 新闻网页贴吧知道音乐图片视频地图百科文库 首页 分类 艺术 科学 自然 文化 地理 生活 社会 人物 经济 体育 历史 特色百科 历史上的今天 数字博物馆 史记·2015 城市百 ...
- 最短路径之Dijkstra(迪杰斯特拉)算法(无向图)
简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.由for循环可知,其时间 ...
- 迪杰斯特拉算法python实现
回顾下最短路径的地杰斯特拉算法 迪杰斯特拉算法是求从某一个起点到其余所有结点的最短路径,是一对多的映射关系,是一种贪婪算法 示例: 算法实现流程思路: 迪杰斯特拉算法每次只找离起点最近的一个结点,并将 ...
- Python实现迪杰斯特拉算法和贝尔曼福特算法求解最短路径
文章目录 (一).题目 (二).导库 (三).绘制带权无向图 (四).获得最短路径 (四).实现最短路径高亮 (五).完整代码 (六).结果展示 关于Python数据分析在数学建模中的更多相关应用:P ...
- 图论的灵魂——带你走进迪杰斯特拉算法的世界
你好,我是小黄,一名独角兽企业的Java开发工程师. 感谢茫茫人海中我们能够相遇, 俗话说:当你的才华和能力,不足以支撑你的梦想的时候,请静下心来学习 希望优秀的你可以和我一起学习,一起努力,实现属于 ...
最新文章
- Linux其实没那么难学
- 什么叫通过超链接实现换页_亚马逊大卖都在用的那些链接 -- 超链接
- CCNA的全套标准实验
- 这样调优:让你的 IDEA 快到飞起来,效率真高!
- 平衡树(模板 and 题目)记录
- HTML/CSS/Javascript代码在线压缩、格式化(美化)工具
- 图像直方图原理与Python实现
- Datastructure
- 正则提取 html 里input 标记的value 值
- pythontcp服务器如何关闭阻塞_python 网络编程(socketserver,阻塞,其他方法)
- Linux内核开发_2_Initramf
- 使用脚本下载.ts文件并合并
- python计算加权平均分_python – 使用pandas数据帧计算加权平均值
- linux宝塔下如何强制ssl,宝塔面板一键安装SSL证书强制HTTPS访问设置
- 因特尔Edison第2站--mraa下gpio
- 每日总结(2021/12/15)
- [相机选型] 普通网络摄像头或小型摄像头和工业相机的区别
- 流的操作(二)如何选择流?
- 苹果cms源码支持php版本_最新影视小程序对接苹果cms详细教程+源码[无授权完美运营版本]...
- Erase/Trim/Discard/Sanitize
热门文章
- 唐骏协查引发大地震:光伏走私到底有多凶?
- SDH PDH 区别与联系
- Spring 框架中都用到了哪些设计模式
- c语言 实现图4-1界面,点击测试进度条后,增加10%,高级C语言实验指导书13级.doc...
- Java for Selenium | Java术语中英文对照
- 英格兰进了六个球都看到了?为什么今年世界杯不卡了?
- JMeter-响应断言
- 聊城大学的计算机专业好还是不好,聊城大学计算机学院
- 计算机系统监控 PerformanceCounter
- 程序员,我为自己代言~