2017 华为软件精英挑战赛

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

第一条: 本地运行都没有问题,交上去确实0分,可能是编译不通过 第一你要下载最新的jdk

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
这个是别人发过的





评论 48
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值