数学建模之2019年亚太杯(APMCM)S奖获奖经历(零基础)

偶然翻到去年写的论文,2019年参加APMCM时写的。(才过了几个月)现在来看,简直惨不忍睹

口说无凭,先让大家先预览一波:
一眼看去就给人混乱不堪的感觉,里面混杂着不同字体和大小的英文,以及“五彩斑斓”的图表,不禁想,我们当时怕是用脚排的版。

既然找到了痛苦回忆的钥匙,就让我们来一探究竟吧。

先谈谈APMCM吧。经过我的多方调查,根据学长学姐介绍,这个比赛主要用来在美赛前练手,等级并不高,获奖也容易。APMCM要求用英语写作,确实可以作为美赛前的一次演练。

不过我当时可没想那么多,不考虑这比赛等级高不高。赛前一个月,数模社团给我们宣传这个比赛时,讲了很多信息,我就看中它一点:可以跨校组队!

可以跨校组队!
可以跨校组队!
可以跨校组队!
可以跨校组队!
可以跨校组队!

这可就有意思了啊,我赶紧向高中室友群里发了这个比赛,拉了两个“亡命之徒”,以“保一冲特”的信心一起报名了这个比赛(报名费100 rmb一队,当时感觉好贵,现在想想,美赛的700大洋简直要人命),其实我们当时连数学建模是啥都不清楚,我的高数也才学到极限,编程c语言只学到条件判断语句(if else)

就这样,一只“零基础”的小白队伍就组成了。
看看队伍简介:

任务 负责人 简介
编程 左家垅皇家男子职业技术学院,自动化类,学过一点c的菜鸟
写作 海鱼 双鸭山大学,法学专业,英语大佬(4级600+),还会Python
模型 小柯 五山镇理工学院,经济学专业,数学大佬,一个星期学完线代

可以看到,我是被两个大佬带着打比赛(能跨校就是爽,刚上大一,在本校也认不得几个)

当时我们也没有基础,所以报完名,我们就互相分配了学习任务,我就学编程(matlab),海鱼练习论文排版,同时学Python,小哥准备模型。

先插播一些我对Python和matlab的感觉。我觉得Python用途广泛,学了后不仅可以建模,还可以搭网站、做人工智能项目、做游戏。Matlab就是建模功能特别强大,也能用来做软件,但是完全版20G的大小实在劝退(当时我百度云下了两天,最近发现了网页版的,不过有些限制,可以写点简单的程序,入口 https://octave-online.net/ 好像要翻越墙壁哈)。

最终,我选择了Python,我认为我们专业实践大于理论,而Matlab主要用于理论分析,Python就可以很方便地进行实践。不过学校的数模培训还是以Matlab为主,好像数学院一般都学matlab,毕竟他们就需要这种功能单一却十分强大的工具。


然而,相信大家也能猜到,计划总是赶不上变化。刚上大学,各种活动、各种好玩的东西冲垮了我们想要好好学习的动力。

这一个月来,我偶然加入了我们学校的创客社团,开心地玩起了arduino,将数模抛在脑后。两个队友也差不多跟我一个情况,这就是传说中的大学生活!

不过,最后一天晚上,我在B站报了下Python和Matlab的佛脚。当时就觉得Python可强了,一定要好好学Python。

终于,到了那一天。

2019年11月29日(左右,记不清了),早上没课,到了7点,我睁开睡眼惺忪的双眼,打开手机一看,亚赛题目发布了。

赶紧进入官网,下载了题目,然后激动地打开PDF。

“真刺激,好几页,全英文,看不懂!”

翻译了一下,然后……还是看不懂……

哈哈,别急,我赶紧在群里跟他们讨论,海鱼给我们分析了一波题目的意思,然后我们随便讨论了下题目,我们都一致认为,A题绝不是我们能做的,连题目都看不懂,B题还比较适合我们这种小白。(A题好像是关于图像识别的,而B题是城市经济分析,感兴趣的可以百度下,很容易找到)

接着因为他们今天课比较多,所以都去上课了。而我,一如既往地玩起了arduino……

不过我们也会想想怎么解题,大家商量好晚上有时间一起讨论。

第一天过去了,海鱼大概写了个框架。我试着用Python把题目里的数据可视化,就是做一些折线图、饼图之类的统计图,最终发现我啥都做不来,什么文件操作,字典,列表都不会,真是“书到用时方恨少”,弄了一下午,查找大量资料,最后做出来,但是太丑了,心里十分烦躁,所以还是放弃了。

到了第二天,这天好像是星期五,快周末了,我还是一样的清闲,今天就只有下午一节足球课,早上我去创客活动室玩了一遭。

下午去上足球课,我就边踢球边想题目,不像以前一样享受踢球,看着大家跑来跑去的,心里很乱,我作为中锋老是传错球,突然,有个同学进球了,大家都疯狂鼓掌。这个时候,一个小灵感突然出现,我赶紧抓住这个小灵感,它就像春笋一样快速在我脑海里面生根发芽。这可能不算什么,但我当时真的是十分激动,踢球也提起劲来。

这个灵感就是关于一个算法的,我当时也不懂什么是算法,就想着虽然我不会Python,但我c语言比较熟悉(当时学到结构体了,c语言理论课上的很快,主要是实践),所以能不能用c语言来建模?

然后我就想到一个游戏算法,这个算法的大概思路就和LOL里面的排位赛一样。

①创建玩家(英雄)
②创建地图(召唤师峡谷)
③创建游戏规则
④玩家相互对战
⑤胜利的奖励积分
⑥一定积分进阶段位
⑦积分、段位排名

这个算法刚好可以解决B题的第三问,大概就是分析每个城市的经济活力,并给他们排序。我设想把每个城市都看作一个玩家,他们的战斗力是经济活力,让他们在峡谷里面相互战斗,自动分一个高下。
原题:

能想到这个,可把我高兴坏了,我赶紧在群里发了一句“想到一个超酷的算法,等晚上写完给你们看看!”

上完课我就一直在想这个算法的实现方法,毕竟我当时只会c语言,而且才学到结构体,我就想着先用结构体创建一个玩家信息,包括名称、攻击力、生命值、防御力、积分,然后设置一些规则,再创建结构体数组,用来保存多个玩家的信息,然后让他们自由对战,积分高的进阶高段位,这样的做法是保证段位很高的不会匹配到段位很低的玩家,毕竟,现实中也很少有大城市会故意针对某个小城市。

就不重新写了,我把那天晚上写的算法思路列出来(原封不动):

提前声明:关于城市生命、防御和攻击的权重是我们凭感觉给的,所以这个算法也不太靠谱,如果能通过数据分析和机器学习得到他们的权重的话,应该会更准确。

排位算法(为解决第三题而生)

——来源于DOTA、LOL以及王者荣耀等网络游戏

一、背景:

在DOTA、LOL以及王者荣耀等网络游戏中,对不同水平玩家以段位的形式进行划分,常见的划分段位从弱到强,段位等级从低到高。系统根据玩家的胜利次数、失败次数和游戏中表现来判定玩家的段位等级。玩家可以通过对战来展现实力,以获取更高等级段位。游戏系统再根据玩家的段位等级进行排序,实现玩家实力的排名。
据此,我们设计出一种类似这种机制的排序方式,能够十分高效地衡量区域经济活力。

二、实现思路:

类似LOL等网游的对战机制,我们将每个城市都设定成一位游戏中的英雄,根据城市企业新建数量、幸存数量和取消数量等经济相关数据,给他们赋予一定的生命值、攻击值和防御值度等属性。我们设置了对战地图,用于模拟各城市在全国范围甚至全世界的竞争,所有参加战斗的城市(英雄)都将在这个对战地图上进行随机对战。每次战斗都以一对一的方式进行,胜利方或失败方会根据剩余生命值和战斗时间等数据增加或减少一定分数。当英雄的分数达到一定值时,便晋级为高一等级的段位。而段位等级和分数便是每个城市对应的经济活力指数。以此来实现城市活力指数的排序。

英雄属性对应关系如下:

项目 Value
Quantity of Newlyestablished Enterprises from 2009 to 2018 生命值
Quantity of Surviving Enterprises in 2019 攻击值
Quantity of Cancelled Enterprises from 2009 to 2018 防御值
  • 如表,通过分析三种数据来确定英雄的初始属性。
  • 新建企业数量决定一个城市经济的总能量大小,因此对应为英雄生命值。
  • 幸存企业数量是城市最直接的核心竞争力,因此对应为英雄攻击值。
  • 取消企业的同时会增加幸存企业的资源量,使幸存企业有更强的耐性,因此对应为英雄防御值。

比如深圳市和上海市的英雄初始属性可设定为(这些数值来源于题目附件表格):

英雄名称:Shenzhen
生命值:203.
攻击值:174.1
防御值:29.0
英雄名称:Shanghai
生命值:204.8.
攻击值:157.4
防御值:47.4
三、战斗开始

现在对战地图上一共有24位英雄,每位英雄都具备了三种初始属性,分别是生命值、攻击值、防御值。
对战开始,英雄们两两随机匹配,进行一对一的战斗。
比如第一场Shenzhen匹配到Shanghai,我们对战斗做出以下规则:

1.对战为回合制,每回合只允许双方各发起一次攻击。
2.系统随机决定由谁发起第一次攻击。
3.战斗中英雄攻击值是一个在一定范围内的随机数,该范围由英雄初始攻击值决定。
4.战斗中英雄防御值和生命值会发生变化。
5.防御值的作用是抵消一定百分比的伤害,防御值越高,抵消百分比越大。
6.最终造成的伤害等于攻击值减去防御值抵消的伤害。
7.造成伤害会使对方生命值降低。
8.当一方英雄生命值小于等于零时,英雄死亡,存活方获得本次胜利。

规则解释:

①模仿经济竞争。
②经济竞争也分先后,此规则用于判断先入为主和后来居上的权重。
③真实社会环境中具有不确定性。

模拟对战:
为了更好理解,我们先进行一场Shenzhen和Shanghai的模拟对战:
1.初始属性对比

属性 数据 数据
英雄名称: Shenzhen Shanghai
生命值: 203.1 204.8
攻击值: 174.1 157.4
防御值: 29.0 47.4

2.对战中真实属性(加了权重的属性):

属性 数据 数据
英雄名称: Shenzhen Shanghai
生命值: 203.1 204.8
攻击值: 43.1~66.2 43.2~67.1
防御值: 29.0(35% 47.4(43%

3.第一回合:
系统随机选择Shenzhen先发起攻击;

ShenzhenShanghai造成 50.4*(1-43%) = 33.768点伤害,Shanghai损失33.768点生命值,同时增加(33.768/2)点防御值(取消企业会增强幸存企业耐力);

……(经历了6个回合)

第八回合ShanghaiShenzhen造成致命伤害,Shanghai获胜,此时Shanghai剩余生命值为23.5
评分:Shanghai 增加 (23.5/8)分剩余生命值除以回合数
Shenzhen减少 (23.5/8)分

:评分标准可以达到剩余生命值越多,分越高;战斗回合越多分越低的目的。

四、排位规则

(1)100分为一个界限,当英雄分数达到界限时可以晋升为更高一级。
(2)段位相差两级及以上的两位英雄不会匹配到一场战斗中。
(3)分数低于界限会被淘汰入低一等级,最低零分
(4)分段如下表:

分数 段位
0-100 青铜
100-200 白银
200-300 黄金
300-400 铂金
400-500 砖石
500-600 超凡
700-800 王者
五、终止条件

当排位不再发生剧烈变化时即可终止,得出各英雄实力排序即各城市经济活力排序,同时各城市的最终分数可以作为经济活力指数用于数据分析。

————————————————————————

上面就是我当时写的思路了(只是初步思路,最终源码有一些变化),写了整整两节自习课,源码太丑,就不放出来了。以前写完还挺骄傲,现在看来,我当时写的都是什么东西。

写完后我跟他们讨论了一些属性权重的问题,最后凭感觉给了一个,然后运算运算,设置不同战斗次数(从5,000次到500,000次)得到了不一样的结果,正好符合我们的预想,最终我综合几个结果就得到如下答案:
City Ranking number Point Ranking
Shanghai 1 1741.84 King
Beijing 2 1512.18 Master
Shenzhen 3 1501.99 Master
Guangzhou 4 1400.24 Master
Chengdu 5 1233.35 Diamond
Chongqing 6 1113.12 Platinum
Tianjin 7 1097.27 Platinum
Suzhou 8 1000.05 Platinum
Nanjing 9 889.58 Gold
Hangzhou 10 799.68 Silver
Wuhan 11 774.96 Silver
Zhengzhou 12 669.47 Silver
Qingdao 13 633.56 Silver
Xian 14 600.70 Silver
Dongguan 15 507.62 Bronze
Ningbo 16 400.76 Bronze
Changsha 17 199.88 Bronze
Shenyang 18 78.86 Bronze
Kunming 19 9.45 Bronze

当时就觉得,这排名还比较符合现实情况,就像前三名的上海、北京、深圳,差不多就是这样的排名。

第三问解决,其他问就没时间了,专门靠海鱼吹了一堆专业术语上去,反正我们也看不懂,就这样混过去了。

不过我们最后一天晚上才写完一半,海鱼写完前半部分,后面关于算法的要我来写,我边写边调BUG,程序写完容易,调BUG可太痛苦了。我从晚上10点开始,一直调到凌晨3点,写论文用两个小时(中文加谷歌翻译),写到5点,我把论文发在群里,让海鱼起床的时候赶紧排下版,我便睡觉。海鱼大概6点起床,7点钟排完版后发群里让我提交,他便去上课了。

我睡到7点多,惊醒,9点就要提交论文了,赶紧起床,看了看提交要求,发现这又是一堆坑,它又要交PDF又要交压缩包,还有承诺书,我把这些全弄完大概8点30了,我就直接提交了。

突然,我看了下官方的示例,发现我们格式完全对不上,什么页码、编号都没写,我又得重新编辑。就在这时,我第一次发现我是多么不会用word这个软件,这一个改完,另一个就乱了,什么页码、目录都不会弄,最后半小时各种百度各种试错倒是弄了一个稍微能接受的,不过连目录都是手写的 ,当时真是啥都不会。

最后一分钟,我把正确排版的文章上传了。

9点后,我们在群里庆祝,太难了、辛苦了……
为了纪念,还留了聊天记录:

然而,我突然发现我又漏了一个格式要求,
就是编号!
我在封面写的正确的编号,但是,我的页顶部编号没改,还是默认编号……

太搞笑了,感觉辛苦白费,索幸主办方似乎没有关注这个错误,我们最后还是获得了一个S奖(别问,问就是S奖)
不信看图:

总算弄完了哈,虽然成绩不佳,但还是很有成就感。感觉亚太赛最好的地方就是给我们提供了一个跨校交流的平台,不仅是以前的高中同学,有些参赛者还会在官方论坛找队友,特别有意思。

后来我打算认认真真准备美赛,并且幸运地找到了两个小伙伴,可惜由于疫情,我们放弃了今年美赛。希望疫情快快结束,我已经迫不及待想回学校跟小伙伴们一起快乐地学习了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章