2017 华为软件精英挑战赛
2017-03-19 18:40
811 查看
2017-04-27
复赛成绩好渣好渣啊。怪复赛初期没有投入,第一周完全没管了。导致后面跟不上节奏了。 http://pan.baidu.com/s/1boOCQTL 初赛复赛代码都放到云盘了。看一下代码就能很清楚知道算法了。
复赛太差就不讲思路了。
说说初赛:
1.采用模拟退火的思路做的,这个其实是其他队伍说效果不错,我才采用的
2.模拟退火会陷入局部最优,我固定T为10了
3.操作只有增加点、删除点、交换点。由于后期交换的作用大
4.迭代次数很关键,由于初中级case迭代次数很多。增加、删除、交换点的情况数是可以固定的,所以是可以枚举的,
因为这里做了一个操作,一旦所有转移情况都试过了就退出,因此我们队初赛的时候是可以控制时间的,初中级常常是满分。
5.获知大佬测试出直连点就能有最优解,所以只用直连点就好啦,可以加速很多
6.由于局部最优解可能很多,所以记录那些状态是访问过的,万一跳到这个状态就不访问了,状态去重。可以用unorder_map做,我直接用bitset搞的
回答上一次的问题:
1.初始化:应该是指抛弃一些点吧,这样初始的时候服务器数量就少了
2.T=10
3.评估函数也是大佬们发现的,直连需求越大的点,越容易是最优解的点,所以直连点分类,需求越大的点越容易保留,越不容易交换,越容易加入。这样可以加速迭代吧。
初赛怎么做了忘记了。。尴尬。。。。。但是主要思考就这些吧。
对了,其实局部最优我们也没有解决,测试样例有些解容易陷入一个较好解,不是最优的。
2017-4-5 新的开始(二)
最后一天咯,祝大家好运。然后我们队已弃疗,不打算修改了。以下几点供大家思考:1.初始化,直连点初始化时一个很优秀的方案,但是初始化的时候你其实可以把服务器限定在一个比较小的范围
2.局部最优解问题,更新的概率不要设置死为0,因为很容易陷入局部最优。
3.迭代优化,随机算法有很多无效的迭代,虽然迭代次数很难提升了,但是能让有效迭代提高就能收敛的更好,那么如何让迭代效率更高呢,那就是设置评估函数,对于点有个概率留在或者抛弃在答案集合中。
以上三个问题解决了,进32应该可以吧,希望不要打脸,明天一看大佬们把我们队打下去了,那我就哭了。。。
2017-4-1 战斗刚刚开始,最后一更~
最后一更:在数据更新以后终于进了前十。 好开心的。然而真的战斗才刚刚开始。大家祝我们好运吧。欢迎各位大佬私信交流。寇嘚虾 | LG | 天津大学 | 寇嘚虾,我们走 |
http://paste.ubuntu.com/24291322/ 这里有文本数据。 最后两列是最后更新的时间和迭代次数。总共使用80s每个case。
附:最后时刻努力准备提排名,无有效交流将不再回复。
PS:这篇文章访问量上100000我就公布第一版的源代码
看完觉得有用,粉我啊~~~我还要更新的
我的百度网盘:http://pan.baidu.com/s/1boOCQTL 资料放这里了(删除算法模板,视频里说会查重。吓死我了。还有判断数据是否合法的代码。。。。。)
type case nodenum linknum costnum servercost widthNeed answer servernum lastUpdatetime dieDaiNum 0 0 160 620 72 400 5491 22243 38 4987744 8833 0 1 160 606 72 400 5108 21932 41 17154391 38128 0 2 160 621 72 400 5587 21312 38 34257124 72893 0 3 160 611 72 400 5785 23158 43 542440 1314 0 4 160 627 72 400 5139 22127 39 6226106 10107 0 5 160 620 72 400 5431 21476 36 1458696 1814 0 6 160 614 72 400 5223 22703 40 15190346 32832 0 7 160 617 72 400 5768 22093 43 13806073 30137 0 8 160 609 72 400 5276 21986 38 1642086 2090 1 0 300 1135 135 400 10132 42147 75 39272372 35807 1 1 300 1134 135 400 8905 40585 68 74427884 58061 1 2 300 1155 135 400 9179 40579 70 67818817 60529 1 3 300 1175 135 400 10485 42189 77 34735045 32831 1 4 300 1169 135 400 9928 40938 70 7346828 5314 1 5 300 1163 135 400 10679 42468 77 50988996 56625 1 6 300 1176 135 400 10347 42804 76 35248808 32830 1 7 300 1149 135 400 9503 39523 68 61649821 44102 1 8 300 1169 135 400 11077 43475 86 3845503 3816 2 0 800 3022 360 400 23491 105329 178 63354612 11524 2 1 800 2994 360 400 25217 108611 199 75847206 19706 2 2 800 3016 360 400 25636 110269 199 72180714 11210 2 3 800 2991 360 400 24461 107534 185 78103581 10801 2 4 800 3021 360 400 26467 110323 196 77699022 9362 2 5 800 2939 360 400 24854 109330 187 65916916 10888 2 6 800 2969 360 400 25711 111035 198 71784436 16795 2 7 800 2976 360 400 25252 111014 199 63073486 14300 2 8 800 2959 360 400 25305 110238 200 58176184 12654
2017-3-26 我把思路完整说一遍吧
补充:计时器的问题,费用流800个点跑一遍最多1s,所以我用的是clock()函数计时的。每次跑完费用流,判断用时大于80s了就结束,输出。#include<ctime>
clock_t start = clock();
do{
}while((clock()-start) < 80*CLOCKS_PER_SEC)
虽然进不了64,但是我还是有话说的。(不懂的先学习一下什么是网络流,然后几个词汇)
我的思路:
根据前面的内容我们建图,每个网络结点跟汇点连边代价为服务器的代价。然后初始图就建好了,这里没有考虑已经选择了一个点当服务器的情况。那我们怎么解决呢。
:::最小费用流,跑出一个路线对吧,然后判断这个路线上除了汇点的最后一个点是不是是服务器,如果不是服务器就标记成服务器,然后把这个点连像汇点的边的代价设置为0.!!!对就是这一步,然后一直重复做就行了。
当然细节处理还是要的,比如这个时候的最短路就是路径长度-服务器费用了。这个方法是一种贪心的策略,还是会有问题的,所以你要想一个策略让最后的结果能够收敛,比如随机初始化几个结点为服务器,然后你就可以得到一个不同答案了。重复随机选个最小值。相信我,800个点的1s中不用就可以跑完,至少可以迭代80次。收敛策略好的话真的能取得一个可以的解。
解答问题:
1. 最后一定是可行解码?
一定!因为是最小费用最大流,最大流就是满足条件的可行方案。把费用流得到残留网络的补建一个新图,(就是说一条边你用了多少流量,新图就连一条多少流量的边),然后从服务器点搜索到消费结点,一定是一条路径!而且绝对不会有环!相信我,骗你的话我的程序是会死循环的。
当然其实这个策略只是得到一个贪心的服务的安置位置。得到的最小费用也不是这个摆放位置下的最小费用(这个trick不隐藏),你要新建一张图,服务器更汇点连边,不是服务器不跟汇点连边,然后再跑一遍费用流,再从这个残留网络去找答案,会有更好的值。
dfs,bfs随便用,可以看成有向无环拓扑图,怎么搜都是一样的。
2.怎么判读输出是否正确呢?
我的百度网盘都提供一个代码了啊!亲,你看一看能看懂的,用就是了,别客气。
有问题的答案代码会提示错误的。
3:还是可行解的问题,
残留网络建立新图以后,每条边记录的是流量(新图不需要费用信息,只需要知道流量信息),从服务器出发只有流量大于0的边才搜索,然后取服务器到消费点的路径上的最小流量值,就是这个路径上的最大流量。搜索完这个路径,更新一下路径上的流量 ,把他们减去路径上那个最小流量值。
搜索完以后,这个新图所有的边的流量都会是0!真的,你思考一下就知道了。
4.怎么选择服务呢
博主也是麻瓜啊,进不了64,我只会随机,而且我只有周末的时候能写代码。况且周末我也有别的任务要完成,好苦逼的。
随机大法好,迭代就行了。你要是嫌弃用用什么蚁群、遗传的策略搞一搞也许效果好一点。
5随机搞的效果怎么样:
我现在还没用迭代的方法:只计算一次得到的结果如下case0-5的,费用+服务器数量。
甚至我想告诉你们,有一个可调的参数是。网络结点到汇点的边的代价,你可以根据消费结点的情况设置这个代价,不一定是服务器的成本!而且这个方式真的能好一点,我新的结果就是服务器代价/10然后提交就比原始的好一点了。
3月25日 |
3294 |
9 |
2923 |
9 |
2032 |
9 |
2631 |
5 |
3046 |
9 |
2017-3-22 这里说说最小费用流、网络流
更过代码可以看我的博客图论专栏,以及百度网盘中acm模板网络流的知识:百度百科 http://baike.baidu.com/link?url=meSaxKRxidfgT7eKYdZJHjbzFBKVlkgdpuQkdsTzoVIysVOvZCQuF30WsZl9gBeD2as--oYCPLHt25-NdK5Qg4O3Iprrhx5r1FSGc-C_EqAsyV9906aG_BGkiOl8s-2R
我简单说说:
要利用网络流算法,首先要构造一张图,这个图要满足有一个源点,汇点。 源点只能流出,汇点只能流入。
直观来说就相当于一个水管的网络,求得一种流水方式,是的起点到终点每秒钟的流量最大。费用流呢,是每条管道每个单位流量有费用,保证最大流量的情况下费用最少
官方给出的图已经包含了这个图中的主要信息,流量上限以及费用。
我们缺少的是怎么建立只有源点,汇点的图:
建图方式: 建立虚拟起点S,虚拟重点T,
对于每个消费结点ID 建立一条 S->ID的边,费用为0,流量为消费结点的需求
对于每个网络中的结点(可以当服务器的)NID, 建立NID->T,费用为0,流量为无穷(很大的数字)
然后对于消费结点和直接相连的网络结点 建立 ID->NID,流量为消费结点的需求,费用为0,。
这样就构造了一张不包含服务器费用的图。跑一遍最小费用流就能获得在不考虑服务器费用的情况下得到的最小费用(那么其实就可以当做是费用下界,同样也能得到上界。。。嘿嘿嘿,这里其实就是每个消费结点连接的网络结点都是服务器的情况)。
当然你还需要一些别的操作来实现最后的目标。。 1. 随机初始化一些点是服务器,然后不是服务器的点不连接T的边,这样得到的就是通过这几个初始服务器得到的最小费用。那可以通过随机设置一些方案来选择最好的方案。
跑完费用流,我们要求一个方案。要新建图,图上的结点还是原来的结点,但是对于一条边,如果这条边 u->v 的流量被占用了x,那么v->u建一条流量为x的边。
这个时候不需要考虑费用了,因为你的费用在费用流计算的时候已经得到了。
建立完图不用什么网络流的优化算法了,直接深度优先搜索DFS(然后还是要控制一下流量的,这条路径上最小的流量就是这条路径的流量),从T到S,搜到一条路径,就是一条要输出的路径(扣除T,S)。
然后方案就出来了。
下面附上相关代码和对应的ACM题,帮助大家理解。
-------------------嘿嘿,怎么选服务器不要问我,我现在就是随便选的一组,然后就输出了,
不过等我有了新版本的时候,我考虑一下把第一版本的思路放出来。
对于代码有什么不懂的,先看资料再尝试问我。
费用流代码SPFA http://blog.csdn.net/firenet1/article/details/47311839
网络流dinic算法
http://blog.csdn.net/firenet1/article/details/46990045
网络流sap算法
http://blog.csdn.net/firenet1/article/details/41659367
2017-3-20 今天终于得分了了::::::::::
首先感谢 华为_判题_吴贺猛 帮助我找到了重要的原因。我提交了很多遍,都是0分, 你想知道为什么0分吗?
明细:
TOPO0 Result error! Score:0,Cost:0,UseTime:0 TOPO1 Result error! Score:0,Cost:0,UseTime:0
用例名称 | Cost | Time(ms) | 用例得分 |
---|---|---|---|
0 | 0 | 0 | 0.00 |
1 | 0 | 0 | 0.00 |
CPU:Intel(R) Xeon(R) CPU E5-2680 V4 @ 2.40GHz
内存:2G
内核:单核
编译器:gcc 4.8.4;java 1.7.0_95;
操作系统:linux Ubuntu 14.04.4 LTS 64位,内核版本 Linux version 3.13.0-108-generic
SDK:为方便选手做题,分别提供c++(兼容c)和Java SDK包供参考(见赛题下载包),详细描述信息请见SDK目录下的readme.txt。
我的百度网盘里放了cmake的源文件,可以用来编译(也放了官方新的jdk)
http://pan.baidu.com/s/1boOCQTL
哦,安装环境前,我用了sudo apt-get remove gcc (cmake) 把原来的东西先清理掉了。
Ubuntu下载
http://www.ubuntu.org.cn/download/alternative-downloads http://cdimage.ubuntu.com/releases/14.04.5/
编译器:vim或者其他的编译器很多,本人热爱codeblocks 16.10
https://launchpad.net/~damien-moore/+archive/ubuntu/codeblocks-stable
官方的运行环境如上,对于linux系统,哪个版本影响并不大,只要64位就可以,但是gcc,g++确实很重要
gcc,g++的安装 http://www.linuxidc.com/Linux/2014-03/97445.htm 如果是新手就严格按要求来吧,
sudo apt-get install libgmp-dev
sudo apt-get install libmpfr4 libmpfr-dev
sudo apt-get install libmpc-dev libmpc2
sudo apt-get install libtool
sudo apt-get install m4
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install autoconf
不过上面几个步骤好像没有顺利通过,但是我也不管了
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-4.8
sudo apt-get install g++-4.8
sudo apt-get install gcc-4.8-multilib
sudo apt-get install g++-4.8-multilib
sudo apt-get install gcc-4.8-doc
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 20
sudo update-alternatives --config gcc
sudo update-alternatives --config g++
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade
上面gcc,g++不要偷懒,少了也不能编译的,最后一步我嫌弃下载太多东西,终止掉了,但是不影响。
搞定了这个,环境就跟服务器上的基本一致了。
然后安装cmake,读readme里,下面一个命令搞定,但是要用root权限
$ ./bootstrap && make && make install
然后环境就搞定了。
但是我遇到了如下问题
make[2]: *** [CMakeFiles/cdn.dir/deploy.cpp.o] Error 1 make[1]: *** [CMakeFiles/cdn.dir/all] Error 2 make: *** [all] Error 2死活不知道原因,但是其实仔细看编译信息,就会发现有编译错误,所以导致这个报错。
因此修改代码就可以了。本地能运行服务器也就能运行了。
至于中文注释什么的都没问题了,刚开始我尝试各种方式,看论坛里的文章规避问题,还是不行。
然后吴老师给我发了编译报错的信息,推荐我使用gcc 4.8. 我看到编译错误以后手动修改了压缩包,提交以后就有分了。
然后修改环境以后自动编译得到的包就能提交运行得分了。
2017-3-19 第一版程序::::::
官方题目中的例子,但是我数了下只有44条边,用于测试吧 标记为case-1.txt (输错了我也不验证了,累死人)28 44 12 100 0 1 20 1 0 2 16 1 0 3 13 1 0 6 13 2 0 7 25 2 0 8 36 2 0 9 14 2 0 16 8 2 0 26 13 2 1 2 5 2 1 3 11 1 1 15 16 2 1 16 24 2 1 18 31 2 1 19 26 2 2 3 7 1 2 4 37 2 2 20 2 2 2 21 5 2 2 25 24 2 3 19 24 2 3 24 17 2 4 5 26 1 4 6 12 1 5 6 14 1 8 21 36 5 9 10 6 1 9 11 14 1 10 11 9 1 10 26 11 5 12 13 15 1 12 14 9 1 12 15 12 1 13 15 27 1 13 14 11 1 14 15 19 1 17 18 22 1 21 22 22 1 21 23 18 1 21 24 14 1 22 23 23 1 22 24 11 1 23 24 23 1 26 27 19 1 0 8 40 1 11 13 2 22 28 3 3 45 4 17 11 5 19 26 6 16 15 7 13 13 8 5 18 9 25 15 10 7 10 11 24 23
第一版程序得到的答案:
以下是附件中的几个测试样例的解:第一版能跑通就很开心了。。。。。当然我问过去年打比赛的赛友,结果比我的好多了。 case-1.txt: Total cost:1123 Server num: 5 需要总流量: 257 提供的流量: 257 case0.txt: Total cost:4160 Server num: 4 需要总流量: 303 提供的流量: 303 case1.txt: Total cost:2951 Server num: 6 需要总流量: 381 提供的流量: 381 case2.txt: Total cost:3864 Server num: 4 需要总流量: 431 提供的流量: 431 case3.txt: Total cost:2765 Server num: 3 需要总流量: 340 提供的流量: 340 case4.txt: Total cost:2525 Server num: 5 需要总流量: 284 提供的流量: 284
百度网盘文件: http://pan.baidu.com/s/1pL35Ull
check.cpp 判断一个输出结果是否正确,有问题会输出一些信息,最后一行输出是这个解的一些信息,费用、服务器数量
case*.txt是数据文件
case*answer.txt 是一个解
别人的抄袭一下;
网络结点数: 28, 网络链路数: 45, 消费结点数: 12 每台服务器的费用为: 100 最小费用:783 服务器结点:0, 3, 22 官方 case0 网络结点数: 50, 网络链路数: 96, 消费结点数: 9 每台服务器的费用为: 260 最小费用:2042 服务器结点:7, 13, 15, 22, 37, 38, 43 官方 case1 网络结点数: 50, 网络链路数: 97, 消费结点数: 9 每台服务器的费用为: 280 最小费用:2136 服务器结点: 6, 7, 13, 17, 35, 41, 48 官方 case2 网络结点数: 50, 网络链路数: 113, 消费结点数: 9 每台服务器的费用为: 300 最小费用:1692 服务器结点: 12, 18, 23, 29, 31, 38, 48 官方 case3 网络结点数: 50, 网络链路数: 97, 消费结点数: 9 每台服务器的费用为: 300 最小费用:2111 服务器结点: 10, 22, 26, 29, 35 官方 case4 网络结点数: 50, 网络链路数: 99, 消费结点数: 9 每台服务器的费用为: 240 最小费用:1967 服务器结点: 12, 15, 20, 22, 26, 37, 48 这个是别人发过的
相关文章推荐
- 2017华为软件精英挑战赛解分析
- 2017华为软件精英挑战赛
- 华为2017软件精英挑战赛 赛程回顾
- [置顶] 2017华为软件精英挑战赛总结
- 2018华为软件精英挑战赛实况记录
- 2017华为软件精英挑战赛总结
- 2017华为软件精英挑战赛
- 2017华为软件精英挑战赛读文件和写文件源代码(C++)
- 2017华为软件精英挑战赛总结
- 2017华为软件精英挑战赛之求解最小费用最大流
- 2017华为软件精英挑战赛--总结
- 最小费用流算法不完全指南-2017华为软件精英挑战赛
- 2017 华为软件精英挑战赛——思路、算法简介
- 2017华为软件精英挑战赛之求解最小费用最大流
- 2017华为软件精英挑战赛总结
- [置顶] 2017华为软件精英挑战赛小结
- 2017华为软件精英挑战赛之求解最小费用最大流
- 2017华为软件精英挑战赛txt数据的读取(MATLAB实现)
- [置顶] 2017华为软件精英挑战赛小结
- 2017华为软件精英挑战赛之求解最小费用最大流