數學建模之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獎)
不信看圖:

總算弄完了哈,雖然成績不佳,但還是很有成就感。感覺亞太賽最好的地方就是給我們提供了一個跨校交流的平臺,不僅是以前的高中同學,有些參賽者還會在官方論壇找隊友,特別有意思。

後來我打算認認真真準備美賽,並且幸運地找到了兩個小夥伴,可惜由於疫情,我們放棄了今年美賽。希望疫情快快結束,我已經迫不及待想回學校跟小夥伴們一起快樂地學習了!

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