2017华为软件精英挑战赛-我们组的解法

来源:互联网 发布:拉普拉斯矩阵 编辑:程序博客网 时间:2024/05/16 04:39

现在差不多过去一个多月了,由于之前没时间写,最近有点时间就写写我们组的做法,我们组在西北赛区没有进决赛,但复赛有进前10。
初赛
题目图片
初赛的话相对比较简单一些,因为限制条件比较少,所以方向会明确一些。题目大概是说把服务器摆放在网络节点某些位置,使得总体的费用比较小,而且满足消费节点容量需求。第一步求最小费用应该是用最小费用流算法(spfa,zkw等,spfa每次寻找当前最便宜的路径,需要注意的是比如两个节点A,B,A与B之间的容量是10G,一旦A->B流了2G流量,则B可以向A流12的流量。另外spfa算法为了加快其速度可以一开始遍历通往终点的那条边,这样可以更快获取最便宜路径),这个应该大多数人都知道,问题是服务器位置和数量,第一眼的想法是就是有一个确定的服务器数量然后摆在一个比较正确的位置,这样就可以使得费用达到全局最优,但是服务器的数量怎么确定的,这是个很复杂的问题,我们开始想的是用多线程,后面听说是单核运行,就放弃了,放弃之后,开始思考在哪个地方放服务器比较合适呢?最初的想法是在放在消费节点上,然后试着让它们向中间移动,但是又觉得这样比较浪费时间,所以放弃了。
后面我们想到的一个办法是计算每个网络节点的权重,权值大的节点放服务器,问题是如何给每个节点算权值,想到的办法是消费节点对这些节点投票包括对自己投票。即给消费节点一个初值,这个初值跟消费节点需要的容量有关,然后从消费节点出发广度优先,这个值随着传播衰减,衰减跟走的路劲的价格(元/G)有关,路径的费用越大,衰减越快,另外跟路劲的容量有关,容量越小衰减越快,经过这个过程,每个节点都能获得一个值,这个过程我们对每个消费节点都会做同样的处理,最终每个网络节点的权值是所有消费节点对它的权值叠加。
这里写图片描述
通过这种方法我们就可以算出每个节点的权值,在这些权值比较大的节点放服务器,可是选多少个点呢,这个时候我们不确定,另外权值的因素我们知道,消费节点容量,消费节点数量,路径的费用,路径的容量这些都会影响权值计算,但是这些因素的作用有多大我们不知道,或者这些因素之间的关系又是什么?这个时候我们会很头疼,实际上这些本来就不确定,这个时候我们可以不用确定,给一个大致的计算形式,然后给一些可调的系数,然后试着修改这些系数,看那个系数比较好,就选择这个系数,通过这种方式可以得到一个比较好的解,在50个点的时候效率很高,但是得到的解并不是最优的,点多的时候,我们尝试的范围会较少,或者采取某些策略,比如确定初始点的数量,可以考虑梯度下降法,这是因为一般来说服务器数量为某个值时费用会比较低。
这里写图片描述
搜索—-改进通过权值选出来的解
1-先试着减少一台服务器,如果减少这台服务器可以降低费用则减少这台服务器,接着试着减少其他服务器(每台服务器只有一次试着减少的机会,失败的话撤销),如果不能再减少服务器了,进入步骤2
2-试着让一台服务器向周围移动,如果可以降低费用则让这台服务器向这个地方移动,更新服务器位置,接着继续试着让其他服务器移动(每台服务器只有一次试着移动的机会,失败的话撤销),如果移动服务器不能降低费用,进入步骤3(这里说一下如果节点数过多的情况,每次试着朝没有放服务器且流过这个节点的流量比较大的节点移动,而不是试着向周围每个节点移动,这样可以节省时间)
3-试着在某个位置增加一台服务器,如果可以降低费用则增加这台服务器,再试着在其他地方增加服务器(每个空位置只有一次试着放服务器的机会,失败的话撤销),如果可以降低费用则这个地方增加这台服务器,直到所有空位置增加服务器都不能降低费用,如果1,2,3只要有一个成功了,则继续执行步骤1,如果都没成功,则退出搜索
通过上面的搜索可以得到一个比较好的局部最优解,但是这个可能不是全局最优解,这个时候我们就得想办法跳出这个局部最优解,方法也比较简单,就是记录所有经历过的状态,就是服务器每经历一个状态都把它记录下来,记录的东西主要是服务器的位置。每当到了一个局部最优解后,试着增加几台服务器,重新搜索求最优解,并且不能再走之前走过的状态。这样就很有可能获取一个比当前好的解。
另外一个问题是就是每次服务器数量一多最小费用流算法时间急剧增加,但是程序最多只能执行90秒,所以要想一些办法估算费用,这样就可以不用调用最小费用流算法,可以节省大量的时间。
0.开始我们把所有流过流量的路径(类似于:消费节点0-A-B-C(服务器)——-流量:5)计算出来,之后才能估算费用
1.减少一台服务器,我们只需要去除掉所有从这台服务器流出的所有流量路径,然后让这些需要流量的消费节点重新寻找其他服务器。得到新的路径并更新路径
2.增加一台服务器的影响我们认为只对其周围的消费节点有影响,这样只需要让其周围的消费节点重新寻找服务器并更新路径。
3.移动一台服务器可以拆分为减少一台服务器和添加一台服务器。
这里写图片描述
到这里初赛的解法说的差不多了,总结一下,开始确定比较可能的点,第二步搜索(减少,替换,增加),搜索到一个局部最优解后想办法跳出局部最优解。
复赛
复赛题目服务器多了限制条件,首先是服务器价格不再是一样的,服务器输出的容量有限制,另外每个节点放一台服务器,费用除了这台服务器要花钱,这个节点也有硬件成本。复赛相对初赛比较难的是服务器类型比较难确定。开始想了很多办法去确定,但是效果都不明显,或者就是找不到方向,后面觉得这本来就是个随机问题,只能确定大致的方向,一开始的想法是放容量最大的服务器,如果出现满足条件的服务器组合,则选择它作为初始解。然后计算一下每台服务器输出的容量,根据它实际输出的容量为它选择一台合适的服务器,选好服务器类型后,开始搜索(减少,移动,增加),这里特别说一下增加,增加的时候各种服务器的类型都试一下,如果节点数太多,没有太多尝试各种服务器的时间,那就选择中间容量的服务器,这样可以得到一个不错的结果,但是离别人差距太大,可能是服务器类型选择有问题,另外一个是服务器数量和位置有问题。
之后想到的是用遗传做,由于我们一开始没有选择这个算法做,所以我们在这个方面做的不是很深,但是这确实是一个可行的方法,我们采取的是一个仿遗传算法,不一定是真正的遗传算法,我们的做法是一开始用权值选择一群点作为初解,这些点可以满足消费节点容量需求。
1.把目前解服务器的输出容量设为无限大,使用最小费用流算法,算出每台服务器实际输出的容量是多少,根据实际输出的容量选择服务器,选择服务器类型后把这些服务器器按照实际输出容量排序,容量大的排在前面。开始减少服务器,先减少输出容量小的服务器,减少的前提是减少该服务器可以降低费用,减少到不能减少服务器的时候进入步骤2。(这里解释一下为什么这么做的原因,实际输出容量大,说明服务器在这个位置运费比较低,这个位置可能是一个比较好的解,减少服务器也是先减少运费贵的服务器(实际输出容量小))
2.记录这个时候服务器的状态(位置和服务器类型),获取到一个局部最优解,之后在之前没有放置服务器的位置(之前记录里没放过)添加一些服务器,不是在所有之前没放过的位置都放服务器,只是一部分位置放服务器(这样做的目的是多执行几轮),如果没有服务器放置则跳到步骤3,有的话继续步骤1
3.获取所有的局部最优解,把这里面涉及到的位置都放一台服务器,放完后,执行步骤1,得个一个不错的局部最优解,同时清空之前放有服务器位置的记录,如果设置的轮数是1,则不执行步骤2,之后直接进入步骤4,如果不是则执行步骤2,重复执行直到设置的轮数都执行完了,才进入步骤4
4.从上面的所有局部最优解中挑选一个最优解,之后相邻的服务器(必须两台服务器有一条边连着)试着交换流量,这里要解释一下,比如服务器A输出200,服务器B输出300,这个时候我们可以试着把A变成容量220,服务器B的容量变为280,如果可以降低费用,它们就交换,如果不能则不交换流量
5.试着让服务器向周围移动,如果可以降低费用,则移动该服务器。

原创粉丝点击