2021华为软件精英挑战赛复赛代码开源

       关于2021年华为软件精英挑战赛的参赛体验请看2021华为软件精英挑战赛的参赛体验

       开源说明:由于训练赛第一的代码在鲁棒性上不够优秀,所以此次代码开源的版本为训练赛17.61亿,为武长赛区第4,复赛正赛16.25亿,为武长赛区第13。由于复赛正赛数据集的偶然因素导致此代码在复赛的表现不佳,但我们队仍然认为此版本代码在解决这个问题上是足够出色的。

1.数据的录入与存储

       当数据录入之后,我们需要用到一些数据结构来存储这些信息

    //对于服务器信息
    public static final Map<String, Integer> name = new HashMap<>(); //服务器编号到类型自定义ID的映射
    public static final Map<Integer, String> type = new HashMap<>();//服务器类型自定义ID到编号的映射
    public static final Map<Integer, int[]> typeInfo = new HashMap<>();//服务器类型自定义ID到类型信息的映射
//对于虚拟机信息
     public static final Map<String, Integer> type = new HashMap<>(); //虚拟机编号到类型自定义ID的映射
    public static final Map<Integer, int[]> typeInfo = new HashMap<>();//虚拟机类型自定义ID到类型信息的映射
2.服务器与虚拟机的bean类

       服务器与虚拟机的bean类用于保存当前已购买的服务器以及当前用户请求部署的虚拟机的信息。
       当需要购买一台服务器时,我们只需要创建一个服务器的ServerBean对象,当用户提出新的虚拟机部署请求时,我们只需要创建一个虚拟机的VMBean对象。
       这样来操作可能会牺牲掉不少的存储空间,尤其是在数据集巨大,需要大量的服务器以及部署大量的虚拟机时,但这样做可以让代码更加的简洁,提升代码的灵活性,更易于维护。

package com.huawei.java.main;

import java.util.HashMap;
import java.util.Map;

//服务器bean类
public  class ServerBean {
     
    //A、B节点的cpu、mem剩余量
    public int A_cpu;
    public int A_mem;
    public int B_cpu;
    public int B_mem;

    //服务器的价格和日常消费
    public final int price;
    public final int dailyCost;

    //服务器ID以及输出时需要的realID
    public final int ID;
    public int realID;

    public void setRealID(int realID) {
     
        this.realID = realID;
    }

    //服务器的类型编号
    public final int TypeID;

    //服务器上安装的虚拟机(键值对:“虚拟机编号->虚拟机的部署方式,-1:双节点部署,0:部署在A节点,1:部署在B节点”
    public final Map<String,Integer>VMs=new HashMap<>();

    public ServerBean(int ID, int typeID) {
     
        Map<Integer,int[]>server= Server.typeInfo;
        int[]info=server.get(typeID);
        A_cpu = info[0]/2;
        A_mem = info[1]/2;
        B_cpu = info[0]/2;
        B_mem = info[1]/2;

        price=info[2];
        dailyCost=info[3];
        this.ID = ID;
        TypeID = typeID;
    }
}

package com.huawei.java.main;

//虚拟机bean类
public class VMBean {
     

    //虚拟机ID
    public final String ID;
    
    //虚拟机所属的服务器的ID,未被安装到服务器上则为-1
    public int ServerID;

    //虚拟机的部署节点,-1:双节点部署,0:部署在A节点,1:部署在B节点
    public int AorB = -1;

    //虚拟机的部署方式,0:单节点部署,1:双节点部署
    public final int type;

    public void setServerID_0(int serverID, int AorB) {
     
        this.ServerID = serverID;
        this.AorB = AorB;
       
    }

    public void setServerID_1(int serverID) {
     
        ServerID = serverID;
       
    }

    //虚拟机的类型ID
    public final int typeID;

    public VMBean(String ID, int typeID, int type) {
     
        this.ID = ID;
        this.typeID = typeID;
        ServerID = -1;
        this.type = type;
    }
}

3.算法流程
  1. 算法思路总述:
           首先,我们是以天为单位一天一天的处理用户请求的,也就是说在处理第x天的请求时,我们只知道第x天前的部署情况,是不知道第x天之后的用户请求的,我们这么做可以更加接近问题的真实场景。
           在处理每日的虚拟机请求时,遵循这样一套标准流程:1.迁移 --> 2.尽可能部署当日需要部署的虚拟机 --> 3.收集不能部署不下的虚拟机,按照算法策略选择购买性价较高的几种服务器并部署 --> 4.删除当日需要删除的虚拟机。
            进行反思时,仍然可以找到这个流程中存在的问题,流程中是先进行的部署,最后才进行的虚拟机删除,这么做看似没有问题,实际上当数据集中大量存在当日部署的虚拟机当日删除的情况时会导致购买多余的服务器,将步骤2和步骤4按照当日用户请求的实际顺序穿插处理明显的更合理的,但由于训练赛的数据集这么做会导致成本小幅上升,所以虽然考虑到了,但仍然没有这样去做。

  2. 迁移策略:
           迁移策略遵循一个原则,将较空的服务器上的虚拟机迁移到较满的服务器上,达到使尽量多的服务器空出来的目的,这样可以使尽可能多的服务器关机,节省日成本消耗。在我们这样去操作的同时,实际上也是服务器的空间的一种更合理的运用——满的服务器尽量的满,使得这部分服务器的空间利用率尽量的高,同时较空的服务器尽量让其不安装任何虚拟机,使得这部分服务器尽量关机。

  3. 部署策略
           迁移完成后,就要对当日的虚拟机进行部署,部署时遵循的原则是优先部署到剩余空间量少也就是相对较满的服务器上,这样做是因为部署是在迁移之后进行的,对虚拟机进行部署时应该尽量不去破坏迁移所达成的服务器的空间分布趋势——也就是说依旧遵循满的尽量满,空的尽量空的原则。

  4. 新服务器的购买策略
           部署完成后,对于当日无法部署的虚拟机,需要购买新的服务器来装下这些虚拟机。对于服务器的购买,采取的是启发式搜索的策略。我们收集当前所有待安装的虚拟机,遍历所有的服务器,将所有的服务器都尝试安装一次(尝试安装需要将服务器安装到不能安装为止),然后对于每台服务器算出一个启发函数,然后选择启发函数结果最优的服务器,然后将相应的虚拟机安装进去,对于剩余待安装的虚拟机,再执行上述操作,直到待安装的虚拟机全部安装完为止。
           启发函数的设计,我们选择的是:服务器每单位已用空间的费用 =(服务器价格购买 +(总天数-当前天数) ∗ * 服务器日消耗费用)/(服务器CPU已用量 ∗ * 拟合权值+服务器MEM已用量 ∗ * 拟合权值),这个函数的函数值越小说明服务器性价比越高,选择的优先级越高。

  5. 算法细节
           三言两语肯定无法说完这样一个庞大的代码工程,一些算法中的代码细节我并没有提到,比如待安装虚拟机的分批操作以解决超时问题,服务器购买策略中如何使得遍历尝试安装的服务器都尽量安装满,迁移中是如何判定服务器过满和过空的等等,感兴趣的朋友可以直接看看源码。

4.算法开源地址:点击这里

https://github.com/HelloWorld-Ian/Huawei_CodeCraft_2021

你可能感兴趣的:(笔记,算法)