2017华为软件精英挑战赛总结

1.题目

本次赛题是一个视频服务器的CDN规划问题
赛题包_百度网盘

2.解题思

2.1 思路一 整数规划

主要是要把模型建出来

包含了
0-1变量->是否布置服务器
边变量-> 表示该边所跑的流量

用glpk试过,变量个数太庞大,内存都开不下,解的效果也不好,只能解很小点数的,连28个点的都解不出来;清华大佬,手写了一份高性能整数规划求解器,解的非常好,膜拜了。

建模思路可以参考清华博士大佬的建模思路:
复赛整数规划模型.docx

2.2 思路二 启发式算法 + 最小费用流

2.2.1 启发式算法

可以用遗传,模拟退火等
如果是遗传的话,染色体编码可以按照0,1编码,布置服务器节点的置为1,没有布置服务器节点的置为0;

2.2.1.1 基于遗传算法的改进

修改策略
加快收敛
1)一轮寻找完以后,先排序,对一轮中最优的 20% 选取进行保留,然后再用这20%的与其他的进行交叉,变异
4)在每轮开始的时候,加入几条历史最优的染色体

跳出局部解
1)搜寻多次
一次搜索完以后,选择最好的1-2条,然后再随机生成种群,再次搜索,思路就是改变初始种群
2)退化,陷入局部最优以后,保留几条比较好的,其余的都重新初始化,再搜索 和 改变初始种群 同理

2.2.1.2 非均衡变异

减搜索,从高位开始,把1的变成0,如果费用降低,则保留0;如果费用增大则保留原来的1;
加搜索,从高位开始,把0的变成1,如果费用降低,则保留1;如果蜂拥增大则保留原来的0;

2.2.2 最小费用流

2.2.2.1 最小费用流建模

最小费用流一般用于求解单源点单汇点的问题,和赛题要求还略有不同,需要增加一个超级源点和一个超级汇点,将多源多汇的费用流问题转化为单源单汇费用流问题,最终建出来的模型如上面整数规划图形所示。
约束1:
连接超级源点到每个服务器节点,将无向边转为两条有向边,cost设置为0,带宽上限设为无穷,可以用最大的可能值代替
约束2:
连接每个消费节点到超级汇点,将无向边转为两条有向边,cost设置为0,带宽上限设为消费节点的需求
约束3:
网络节点内部都是互相连接的,将无向边转为两条有向边,cost和带宽上限根据读取的图信息来设置
约束4:
网络节点到消费节点设为双向边,cost按读取的图信息来设置,带宽上限设为消费节点的需求

2.2.2.2 最小费用流入门

概念
原理解析

2.2.2.3 最小费用流 之 增广路

一种是在可行流基础上进行增广,每次按照最小费用增广,直到没有办法再增广则算法结束,求得的就是最小费用最大流;

2.2.2.4 最小费用流 之 费用最小的最大流

在可行流基础上先寻找最大流,找到最大流以后想办法将费用降到最低

2.2.2.5 最小费用流代码实现
2.2.2.5.1 SPFA

SPFA方式源代码


/***************************************************
算法引入:
任何容量网络的最大流流量是唯一且确定的,但是它的最大流f并不是唯一的;
既然最大流f不唯一,因此,如果每条弧上不仅有容量限制,还有费用r;
即每条弧上有一个单位费用的参数,那么在保证最大流的前提下;
还存在一个选择费用最小的最大流问题,即为最小费用最大流问题;

算法思想:
寻找最大流的方法是从某个可行流出发,找到关于这个流的一条增广路P;
沿着P调整f,对新的可行流又试图寻找关于它的增广路,循环直至不存在增广路为止;
要求最小费用最大流:
如果f是流量为f1的可行流中费用最小者,而p是关于f的所有增广路中费用最小的增广路;
那么沿着p去调整f,得到可行流_f,就是流量为f1的所有可行流中的费用最小者;
这样当f是最大流时,它也就是所要求的最小费用最大流了;

算法内容:
在寻找关于f的最小费用增广路的过程中;
需要构造一个关于f的伴随网络W(f);
把在原网络中寻找关于f的最小费用增广路转换为在伴随网络W(f)中寻找从Vs到Vt的最短路问题;

其中伴随网络W(f)构造为:
顶点为原网络中的顶点;
原网络中的每条弧<u,v>变成两个方向相反的弧<u,v>和<v,u>;
在W(f)中每条弧<u,v>的权值为:
if(f(u,v)<c(u,v))
    W(u,v)=r(u,v);
else if(f(u,v)==c(u,v))
    W(u,v)=无穷大(可省略);
if(f(u,v)>0)
    W(v,u)=-r(u,v);
else if(f(u,v)==0)
    W(v,u)=无穷大(可省略);

算法流程:
①开始取f(0)={0};
②一般若在第k-1步得到的最小费用流为f(k-1),则构造伴随网络W(f(k-1));
③在W(f(k-1))中寻找从Vs到Vt的最短路,若不存在则转⑤,存在转④;
④在原网络G中得到相应的增广路P,在P上对f(k-1)进行调整;调整后新的可行流为f(k),转②;
⑤f(k-1)为最小费用最大流,算法完毕;

算法测试:
HDU1533,ZOJ2404,POJ2195(Going Home);
题意:
在一个网络地图上,有n个小人和n栋房子;
在每个单位时间内,每个人可以往水平方向或垂直方向移动一步,走到相邻的方格中;
对于每个小人,走一步需支付一美元,直到他走入房子里,且每栋房子只能容纳一个人;
求让n个小人移动到n个不同的房子,求需要支付的最小费用;
****************************************************/

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<queue>
using namespace std;

int n,m;
const int N=250;
const int M=10000;
const int MAX=0xffffff;
ch
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值