xucher / Huawei-CodeCraft-2022

华为软件精英比赛初赛思路及代码(武长初赛第10)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

一、理想条件下的最优解

优化时尽量往最优解靠近,并充分考虑不能达到理想条件时如何处理

  • 每个边缘节点的后5%(记为 **N5 **时刻)均为其最大容量
  • 前95%为所有时刻总剩余带宽取均值

二、目标拆分

问题的目标为每个节点的95%分位点之和最小,可拆分为以下两个目标:

  1. 所有节点的 N5时刻分配的总需求最大化

    • ==分配N5时刻时尽量保证总需求较大的时刻的剩余需求较为平均==

    • 总需求较小的时刻不会影响目标

  2. 每个时刻剩余节点尽量取除N5节点外剩余总需求的均值(平均最优的条件是各个时刻除N5节点外剩余需求相同)

    • 如果不是均值,必然存在某个节点总需求大于均值,若这个值为分位点,目标一定差于取均值的情况
    • 目标1最大化可以使得目标2的均值最小化

三、算法结构

3.1 贪心构造可行解

3.1.1 选择每个节点的N5时刻

评估方法
  • 给定一个节点,计算每个时刻该节点能够接受的最大剩余总需求 LD
  • 将 LD 最大的 N5 个时刻定为 N5时刻
    • 剩余时刻可能有与N5时刻相同的 LD,考虑加入随机选择
节点分配顺序

若两个节点 S1, S2 可服务相同客户 C,先分配的节点 S1会先占据客户 C 的需求,可能导致节点 S2 没有足够需求,且节点 S1本可以被分配其他客户的需求以达到最大容量,这种情况下的 N5 节点分配是有优化空间的

方法1:按照输入文件中节点顺序

方法2:划分优先级,按优先级从高到低分配,优先级越高,可调整空间越大

  • 节点优先级标准:能够服务的客户数
  • 客户优先级标准:可分配的节点数

两个方法的效果对比

  • 方法2在某些算法差于方法1,但是总体上看更好
官方算例中节点特征
  • 存在未与任何客户相连的边缘节点(记为无效节点),算法中不需要考虑这些节点
  • 节点可按可服务客户是否完全相同分组,分组可以在一定程度上提升速度

3.1.2 按时刻均化剩余节点需求

粗分
  • 给定时刻,计算除已分配到N5节点外的剩余总需求 LD,除N5节点及无效节点之外的可分配节点数 LS,计算节点需求均值 EV
  • 实际分配时,尽量给每个节点分配 EV 的总需求。需要考虑以下两个不能达到 EV 的情况
    • 节点的容量不够
    • 节点可分配的剩余需求不够
  • 节点总需求不能达到 EV 时,计算剩余需求及节点个数,更新 EV。EV 只会增大,因此可以固定该节点需求,现在不能分配后面也不行。

分配顺序会影响能否得到可行解,按增广路的方式建立残量图可消除分配顺序影响

分配剩余未分配需求
  • 给定一个需求未完全分配的客户 C,寻找以客户 C 为起点,终点为节点 S(即包含奇数条边)的增广路,增广路的最大流量记为 MF
  • 客户 C 可分配到节点 S 的需求:min { 客户 C 剩余需求,MF,节点剩余容量 }
按时刻平衡
  • 给定时刻,计算除已分配到N5节点外的剩余总需求 LD,除N5节点及无效节点之外的可分配节点数 LS,计算节点需求均值 EV
  • 计算除N5节点及无效节点之外的可分配节点的超出需求 Exceed:节点已分配需求 - EV
  • 寻找以 Exceed 小于 0 的节点 S1 为终点,Exceed 大于 0 的节点 S2 为起点的增广路(偶数条边),增广路的最大流量记为 MF
  • 节点 S2 可分配到 S1的需求:min { -Exceed[S1], Exceed[S2], MF, 节点 S1剩余容量 }
  • 类似粗分,更新节点需求均值 EV
  • 由于 EV 为向下取整,可能存在某些节点总需求较大,但不超过可分配节点数
  • 均值增加后,重新回到第一个 site 开始分配

3.2 搜索更合适的 N5 时刻

T1为换出时刻,剩余需求均值记为 AVG1,N5节点数记为 X1;

T2为换入时刻,剩余需求均值记为 AVG2,N5节点数记为 X2;

给定一个节点 Site

  • 记 T1 时刻总需求为 $D1$
    • $D1 < AVG1$,T1 时刻其他节点总需求一定不变, $\Delta AVG1 < 0$
    • $D1 = AVG1$,T1 时刻其他节点总需求一定不变, $\Delta AVG1 = 0$
    • $D1 > AVG1$,T1 时刻其他节点总需求可能增加, $\Delta AVG1 > 0$
  • 记 T2 时刻总需求为 $D2$调整后 T2 时刻总需求 $D2' \geq D2$
    • $D2' = D2$ 则 T2 时刻N5节点总需求一定不变
    • $D2' > D2$ 则 T2 时刻N5节点总需求可能减小

优化条件:T2时刻一定存在 N5节点,且 $D2' > D2$

双交换条件:均能使另一个时刻N5节点需求减小

缓存:若时刻中N5节点未变,则上一次的计算结果有效

邻域(更改节点的N5时刻)

  • 给定节点,交换一个 N5 时刻 T1 与非 N5 时刻 T2
  • ==限制邻域==
    • T1可以优先考虑未达到最大容量限制的节点
    • T1优先考虑被选为N5,但是并非排序N5的节点
    • T2 的搜索范围限制在分位点的效果比分位点之前的 K 个点好
    • 给定一个时刻,可优先考虑总需求较大的节点作为T2
  • 考虑所有较大时刻的剩余需求较为平均
  • 若一个时刻中,N5节点均为最大容量,其余均为剩余容量的均值,可视为完美分配,不更改其N5节点
  • 若一个节点容量较小,且均达到满载,可不考虑

若邻域变换后目标值未更新,需要退回原来状态

3.3 调整

  • 记录各个节点分位点,分位点从 N5 到 Q
  • 设定每个节点的可调整需求为与分位点Q的差,节点总需求大于分位点Q设为0
  • 按照节点顺序(==按N5分位点降序==)调整每个节点的N5分位点,调整目标记为分位点 NK
    • 判断节点的 N5 到 NK - 1 分位点能否降低到分位点 NK
    • 均可以降低到分位点 NK 则进行调整
    • 否则将节点的可调整需求视为与分位点 NK - 1 的差
    • 判断完所有节点后调整目标记为分位点 NK + 1
  • ==分位点Q之后,判断是否存在总需求较小的节点,将其分位点设为0==
按节点优化方案
  • ==判断每个节点的分位点能否下降==

  • ==如果一个节点的分位点非常接近最大容量,且难以降低,可以考虑把其他时刻的load增加到与其相同的水平==

    • 其他时刻不一定会影响分位点
  • 如果一个节点的分位点远小于最小的 N5 时刻容量,考虑将其分位点设为 0

四、速度优化

  • 节点分组

  • ==多线程==:服务器环境为 4U 4G

五、继续改进思路

记除N5节点已接收流量外的剩余流量,除以剩余的有效节点个数的商为剩余均值

解的优化过程中,剩余均值最大的时刻,剩余均值总体呈下降趋势

  • 选择N5节点时,考虑让所有时刻的最大剩余均值最小

搜索时平均的复杂度如果可以降低,就有足够的时间使用更高级的启发式优化方法

  • 每个时刻的节点结构是不变的,考虑对客户节点建图
    • 按照可分配的边缘节点是否完全相同,对客户节点分组
    • 给定一个客户节点组,其总需求可以分为两部分
      • 留在本组的需求,平均分配给该组的所有节点
      • 调整到其他节点组的需求,组间最大调整量为,这两个组公共客户的总需求

About

华为软件精英比赛初赛思路及代码(武长初赛第10)


Languages

Language:C++ 99.6%Language:CMake 0.4%