導航:首頁 > 源碼編譯 > 演算法集訓隊作用

演算法集訓隊作用

發布時間:2022-07-13 20:23:19

A. 高中才開始學習信息競賽有機會進入國家集訓隊嗎

我從小六開始學,一直到初三前都沒怎麼學,大概都是在搞文化課(不過搞得也差),基本沒有提升,oi省內排名也一直在50+左右徘徊。
初三的時候一沖動就搞了一兩個月停課訓練,noip570,然後進了b隊,簽了t大一本,最終noi2017rank38.

高中生搞競賽停課的話,訓練的效率應當是比初中生每天頹廢摸魚要高的多的,況且我也算比較弱也比較頹廢的(嚴重的時候一天一個多小時訓練時間全部在頹),真正有實力也勤奮的大佬認真搞一年應該頂我初中瞎搞三年(比如今年的zzx大佬)。

所以不但有機會,而且機會還挺大的。

B. 全世界最強的演算法平台codeforces究竟有什麼魅力

簡單介紹一下codeforces這個網站,codeforces位於宇宙編程最強的毛國。據說最早是由俄羅斯的一群大學生維護的,它最大的特點就是代碼和題解的公開。所有人都可以隨意查看其它大牛的代碼,可以說是非常具有開源精神了。

codeforces很大的特點就是題目兼容並蓄,什麼難度等級的題目都可以找到。並且題目很有意思,往往思維陷阱比較多,也就是思維題比較多。對於數據結構以及演算法的考察相對弱一些,更多的時候往往是告訴你用什麼演算法你也不知道怎麼做……

codeforces另外一個很大的特點就是它有自己的上分系統,基本上每周會舉辦一到兩次在線的演算法比賽。一般的比賽時長是兩個小時,只要注冊賬號就可以免費參加。我記得當年第一次參加比賽會獲得一個初始分是1500,然後根據你在比賽當中的表現上分或者減分。由於參加的選手水平實力強度不一,所以它開設了好幾個檔次(div),不同層次的選手面對的題目難度也不一樣,這樣保證了大家都可以愉快地參賽。

codeforces在比賽的時候只會測試一小部分數據,真正的測試集會放到賽後進行測試。所以在比賽中測試通過的代碼,只是通過了小數據驗證,很有可能有隱藏的問題沒被發現。當你通過了這道題之後,你就可以去查看其他通過人的代碼,去分析它們有沒有問題,如果發現了bug,可以構造一份數據hack掉他的提交。hack成功之後,你會獲得分數的獎勵。

你可以雙擊打開其他人的提交記錄,去閱讀他們的代碼。到了比賽後期,能做的問題做的差不多了之後,就進入了緊張刺激的互相hack階段。講道理,這比只是單純做題的競賽要有趣多了。

以前我們acm集訓隊經常晚上一起打codeforces的比賽,有時候看到隊友在一個房間里,還會互相關注一下近況,互相hack一把,不得不說現在懷念起來還是非常有意思的。

好了,關於codeforces網站就介紹到這里了,如果你也對演算法感興趣的話,不妨試著用一下它吧,相信你也會找到演算法的樂趣。

C. 進入acm協會能學到什麼

哈,我就是acm校集訓隊的同學~~

具體的,演算法,數據結構知識都會學的很深刻,起碼比計算機專業的非acm的同學,強很多了。
然後,代碼能力的提升,也是非常非常大的。認認真真做過acm的同學就會有體會,寫個代碼要比沒做過的容易得多,而且效率高。
再有就是團隊配合,三人組隊賽,配合很重要的,你們之間會有默契,以後做什麼事情都會很順利的~~

最主要的,計算機專業招聘去IT企業,筆試面試的時候都會有演算法題,這個做過acm的是非常吃香的,沒做過的只能乾瞪眼了~~

D. 參加acm需要學什麼

其實acmer們都是自己訓練的啊,這種東西只能自己學哈~先從基本的開始吧,把c/c++練熟了,java要掌握一些。然後就是演算法上的東西了。演算法的學習是比較痛苦的,書建議看演算法導論,演算法藝術與信息學競賽,具體數學,柔性字元串匹配,然後是去各大oj上訓練做題,推薦poj,zoj,hdoj,還有各種比賽。下面是詳細的訓練方法~

訓練方法。現在這個賽季基本就算結束了,所以可以從自身能力開始提升,先把演算法掌握的全面一些。模擬,數學,計算幾何,圖論,數據結構,動態規劃,搜索,字元串匹配,貪心,這些知識都要進行學習。如果來不及的話,盡量保證,每一塊知識都能有兩個人覆蓋到,這樣三人組隊,可以保證穩定發揮。個人訓練可以自己做題,按各個知識點來。也可以穿插著去做做比賽,topcoder的srm和codeforces都很不錯,還有zoj的月賽。這都是平時練習的好機會。

比賽前一兩個月,要進行隊伍磨合。組隊做一些比賽,可以去hust的oj上自己掛比賽。注意分配幾時,然後讀題要仔細,分題的時候要清醒,千萬別覺得這個題可做,就直接搞,一定要和隊友商量。卡題的時候,切記不要沖動,亂交會導致罰時飆升啊,那樣很痛苦的。

然後熱身賽記得測一下longlong類型的輸出是用lld還是I64d,然後放平心態就可以了~

E. 一個計算機專業大學生,如何看待學校的ACM集訓隊我不懂為什麼那麼多人擠破腦袋想加入我覺得一名優

啥?居然有很多人想擠破腦袋進ACM集訓隊這樣的事情。。。。。
估計是因為很多人盲目的把ACM看待為高中時候數學化學競賽的性質的原因吧。。。
以我的經歷來看,計算機演算法競賽對人的成長作用毫無疑問是不可估量的,但這絕不同於高中時那些競賽的性質。選擇ACM不是說是為了鍛煉,更不可能是為了證書(普通比賽的證書隨便一大把,但想拿到有影響力的證書簡直是難的可怕)。選擇ACM就意味著你選擇了你以後的道路,為什麼這么說呢,其一,研究演算法是一項極其需要腦力和時間的事情,這就意味著你必須要放棄其他許多事情,只能專其一,盡管ACM跟NOI相比跟側重於運用而不是創新;其二,可以說:一入此門深似海。。。這會徹底顛覆你以前思考問題的模式,學會並習慣一種全新的的思維模式。
這就是我自己親身經歷的體會,你必須有極大的興趣才能堅持的下來(比如你很多時候會對著電腦查BUG 10+小時或者一道題目要近一個月才想通),所以我敢說那些擠破腦袋想加入的95%的人會很快就放棄

F. 求助:學校太爛,好像沒有集訓隊,怎麼參加acm

應該是沒有蹭別的學校的名額參加acm的~要組隊的話,還是找自己學校的人組~如果學校支持的話最好,不支持的話,就很困難了~如果數學好的話對搞acm肯定是有幫助的,但也不是絕對的,原先的acm比賽偏向演算法,搞得像是OI的加強版~現在的話越來越偏重對編碼能力的要求~現在賽制是先參加各個賽區的網路賽預賽(網路賽是沒有參賽限制的,只要能湊到3個人就行),再參加區域賽,再參加世界總決賽,亞洲一共15個賽區,中國大陸5個,每年的9月到11月是各大洲的區域賽,網路預賽一般在區域賽前兩三個星期比的~過了網路賽才有參加區域賽現場賽的資格~網路賽的時候競爭就挺激烈的了~搞acm跟大學的好壞沒決定性的關系,主要是看學校的重視程度,每年都有一些非211高校進世界總決賽的~好好努力吧~

G. 中專集訓隊有必要進嗎

有必要。集訓後可參加中職技能大賽。對中職學生考查本專業比較具有代表性的技能,能夠一定程度上反映社會對職業院校學生能力的要求,通過參加技能大賽,可以全面發展專業技能,提升專業素養,對以後在大學之後專業技能的學習具有較強的促進作用。

H. acm初學者要准備什麼 看什麼書啊

剛剛接觸信息學領域的同學往往存在很多困惑,不知道從何入手學習,在這篇文章里,我希望能將自己不多的經驗與大家分享,希望對各位有所幫助。
一、語言是最重要的基本功

無論側重於什麼方面,只要是通過計算機程序去最終實現的競賽,語言都是大家要過的第一道關。亞洲賽區的比賽支持的語言包括C/C++與JAVA。筆者首先說說JAVA,眾所周知,作為面向對象的王牌語言,JAVA在大型工程的組織與安全性方面有著自己獨特的優勢,但是對於信息學比賽的具體場合,JAVA則顯得不那麼合適,它對於輸入輸出流的操作相比於C++要繁雜很多,更為重要的是JAVA程序的運行速度要比C++慢10倍以上,而競賽中對於JAVA程序的運行時限卻往往得不到同等比例的放寬,這無疑對演算法設計提出了更高的要求,是相當不利的。其實,筆者並不主張大家在這種場合過多地運用面向對象的程序設計思維,因為對於小程序來說這不旦需要花費更多的時間去編寫代碼,也會降低程序的執行效率。

接著說C和C++。許多現在參加講座的同學還在上大一,C的基礎知識剛剛學完,還沒有接觸過C++,其實在賽場上使用純C的選手還是大有人在的,它們主要是看重了純C在效率上的優勢,所以這部分同學如果時間有限,並不需要急著去學習新的語言,只要提高了自己在演算法設計上的造詣,純C一樣能發揮巨大的威力。

而C++相對於C,在輸入輸出流上的封裝大大方便了我們的操作,同時降低了出錯的可能性,並且能夠很好地實現標准流與文件流的切換,方便了調試的工作。如果有些同學比較在意這點,可以嘗試C和C++的混編,畢竟僅僅學習C++的流操作還是不花什麼時間的。

C++的另一個支持來源於標准模版庫(STL),庫中提供的對於基本數據結構的統一介面操作和基本演算法的實現可以縮減我們編寫代碼的長度,這可以節省一些時間。但是,與此相對的,使用STL要在效率上做出一些犧牲,對於輸入規模很大的題目,有時候必須放棄STL,這意味著我們不能存在「有了STL就可以不去管基本演算法的實現」的想法;另外,熟練和恰當地使用STL必須經過一定時間的積累,准確地了解各種操作的時間復雜度,切忌對STL中不熟悉的部分濫用,因為這其中蘊涵著許多初學者不易發現的陷阱。

通過以上的分析,我們可以看出僅就信息學競賽而言,對語言的掌握並不要求十分全面,但是對於經常用到的部分,必須十分熟練,不允許有半點不清楚的地方,下面我舉個真實的例子來說明這個道理——即使是一點很細微的語言障礙,都有可能釀成錯誤:

在去年清華的賽區上,有一個隊在做F題的時候使用了cout和printf的混合輸出,由於一個帶緩沖一個不帶,所以輸出一長就混亂了。只是因為當時judge team中負責F題的人眼睛尖,看出答案沒錯只是順序不對(答案有一頁多,是所有題目中最長的一個輸出),又看了看程序發現只是輸出問題就給了個Presentation error(格式錯)。如果審題的人不是這樣而是直接給一個 Wrong Answer,相信這個隊是很難查到自己錯在什麼地方的。

現在我們轉入第二個方面的討論,基礎學科知識的積累。

二、以數學為主的基礎知識十分重要

雖然被定性為程序設計競賽,但是參賽選手所遇到的問題更多的是沒有解決問題的思路,而不是有了思路卻死活不能實現,這就是平時積累的基礎知識不夠。今年World Final的總冠軍是波蘭華沙大學,其成員出自於數學系而非計算機系,這就是一個鮮活的例子。競賽中對於基礎學科的涉及主要集中於數學,此外對於物理、電路等等也可能有一定應用,但是不多。因此,大一的同學也不必為自己還沒學數據結構而感到不知從何入手提高,把數學撿起來吧!下面我來談談在競賽中應用的數學的主要分支。

1、離散數學——作為計算機學科的基礎,離散數學是競賽中涉及最多的數學分支,其重中之重又在於圖論和組合數學,尤其是圖論。

圖論之所以運用最多是因為它的變化最多,而且可以輕易地結合基本數據結構和許多演算法的基本思想,較多用到的知識包括連通性判斷、DFS和BFS,關節點和關鍵路徑、歐拉迴路、最小生成樹、最短路徑、二部圖匹配和網路流等等。雖然這部分的比重很大,但是往往也是競賽中的難題所在,如果有初學者對於這部分的某些具體內容暫時感到力不從心,也不必著急,可以慢慢積累。

競賽中設計的組合計數問題大都需要用組合數學來解決,組合數學中的知識相比於圖論要簡單一些,很多知識對於小學上過奧校的同學來說已經十分熟悉,但是也有一些部分需要先對代數結構中的群論有初步了解才能進行學習。組合數學在競賽中很少以難題的形式出現,但是如果積累不夠,任何一道這方面的題目卻都有可能成為難題。

2、數論——以素數判斷和同餘為模型構造出來的題目往往需要較多的數論知識來解決,這部分在競賽中的比重並不大,但只要來上一道,也足以使知識不足的人冥思苦想上一陣時間。素數判斷和同餘最常見的是在以密碼學為背景的題目中出現,在運用密碼學常識確定大概的過程之後,核心演算法往往要涉及數論的內容。

3、計算幾何——計算幾何相比於其它部分來說是比較獨立的,就是說它和其它的知識點很少有過多的結合,較常用到的部分包括——線段相交的判斷、多邊形面積的計算、內點外點的判斷、凸包等等。計算幾何的題目難度不會很大,但也永遠不會成為最弱的題。

4、線性代數——對線性代數的應用都是圍繞矩陣展開的,一些表面上是模擬的題目往往可以藉助於矩陣來找到更好的演算法。

5、概率論——競賽是以黑箱來判卷的,這就是說你幾乎不能動使用概率演算法的念頭,但這也並不是說概率就沒有用。關於這一點,只有通過一定的練習才能體會。

6、初等數學與解析幾何——這主要就是中學的知識了,用的不多,但是至少比高等數學多,我覺得熟悉一下數學手冊上的相關內容,至少要知道在哪兒能查到,還是必要的。

7、高等數學——純粹運用高等數學來解決的題目我接觸的只有一道,但是一些題目的敘述背景往往需要和這部分有一定聯系,掌握得牢固一些總歸沒有壞處。

以上就是競賽所涉及的數學領域,可以說范圍是相當廣的。我認識的許多人去搞信息學的競賽就是為了逼著自己多學一點數學,因為數學是一切一切的基礎。

三、數據結構與演算法是真正的核心

雖然數學十分十分重要,但是如果讓三個只會數學的人參加比賽,我相信多數情況下會比三個只會數據結構與演算法的人得到更為悲慘的結局。

先說說數據結構。掌握隊列、堆棧和圖的基本表達與操作是必需的,至於樹,我個人覺得需要建樹的問題有但是並不多。(但是樹往往是很重要的分析工具)除此之外,排序和查找並不需要對所有方式都能很熟練的掌握,但你必須保證自己對於各種情況都有一個在時間復雜度上滿足最低要求的解決方案。說到時間復雜度,就又該說說哈希表了,競賽時對時間的限制遠遠多於對空間的限制,這要求大家盡快掌握「以空間換時間」的原則策略,能用哈希表來存儲的數據一定不要到時候再去查找,如果實在不能建哈希表,再看看能否建二叉查找樹等等——這都是爭取時間的策略,掌握這些技巧需要大家對數據結構尤其是演算法復雜度有比較全面的理性和感性認識。

接著說說演算法。演算法中最基本和常用的是搜索,主要是回溯和分支限界法的使用。這里要說的是,有些初學者在學習這些搜索基本演算法是不太注意剪枝,這是十分不可取的,因為所有搜索的題目給你的測試用例都不會有很大的規模,你往往察覺不出程序運行的時間問題,但是真正的測試數據一定能過濾出那些沒有剪枝的演算法。實際上參賽選手基本上都會使用常用的搜索演算法,題目的區分度往往就是建立在諸如剪枝之類的優化上了。

常用演算法中的另一類是以「相似或相同子問題」為核心的,包括遞推、遞歸、貪心法和動態規劃。這其中比較難於掌握的就是動態規劃,如何抽象出重復的子問題是很多題目的難點所在,筆者建議初學者仔細理解圖論中一些以動態規劃為基本思想所建立起來的基本演算法(比如Floyd-Warshall演算法),並且多閱讀一些定理的證明,這雖然不能有什麼直接的幫助,但是長期堅持就會對思維很有幫助。

四、團隊配合

通過以上的介紹大家也可以看出,信息學競賽對於知識面覆蓋的非常廣,想憑一己之力全部消化這些東西實在是相當困難的,這就要求我們盡可能地發揮團隊協作的精神。同組成員之間的熟練配合和默契的形成需要時間,具體的情況因成員的組成不同而不同,這里我就不再多說了。

五、練習、練習、再練習

知識的積累固然重要,但是信息學終究不是看出來的,而是練出來的,這是多少前人最深的一點體會,只有通過具體題目的分析和實踐,才能真正掌握數學的使用和演算法的應用,並在不斷的練習中增加編程經驗和技巧,提高對時間復雜度的感性認識,優化時間的分配,加強團隊的配合。總之,在這里光有紙上談兵是絕對不行的,必須要通過實戰來鍛煉自己。

大家一定要問,我們去哪裡找題做,又如何檢驗程序是否正確呢?這大可不必擔心,現在已經有了很多網上做題的站點,這些站點提供了大量的題庫並支持在線判卷,你只需要把程序源碼提交上去,馬上就可以知道自己的程序是否正確,運行所使用的時間以及消耗的內存等等狀況。下面我給大家推薦幾個站點,筆者不建議大家在所有這些站點上做題,選擇一個就可以了,因為每個站點的題都有一定的難易比例,系統地做一套題庫可以使你對各種難度、各種類型的題都有所認識。

1、Ural:

Ural是中國學生對俄羅斯的Ural州立大學的簡稱 ,那裡設立了一個Ural Online Problem Set,並且支持Online Judge。Ural的不少題目演算法性和趣聞性都很強,得到了國內廣大學生的厚愛。根據「信息學初學者之家」網站的統計,Ural的題目類型大概呈如下的分布:

題型
搜索
動態規劃
貪心
構造
圖論
計算幾何
純數學問題
數據結構
其它

所佔比例
約10%
約15%
約5%
約5%
約10%
約5%
約20%
約5%
約25%

這和實際比賽中的題型分布也是大體相當的。有興趣的朋友可以去看看。

2、UVA:

UVA代表西班牙Valladolid大學(University de Valladolid)。該大學有一個那裡設立了一個PROBLEM SET ARCHIVE with ONLINE JUDGE ,並且支持ONLINE JUDGE,形式和Ural大學的題庫類似。不過和Ural不同的是,UVA題目多的多,而且比較雜,而且有些題目的測試數據比較刁鑽。這使得剛到那裡做題的朋友往往感覺到無所適從,要麼難以找到合適的題目,要麼Wrong Answer了很多次以後仍然不知道錯在那裡。 如果說做Ural題目主要是為了訓練演算法,那麼UVA題目可以訓練全方位的基本功和一些必要的編程素質。UVA和許多世界知名大學聯合辦有同步網上比賽,因此那裡強人無數,不過你先要使自己具有聽懂他們在說什麼的素質:)

3、ZOJ:

ZOJ是浙江大學建立的ONLINE JUDGE,是中國大學建立的第一個同類站點,也是最好和人氣最高的一個,筆者和許多班裡的同學就是在這里練習。ZOJ雖然也定位為一個英文網站,但是這里的中國學生比較多,因此讓人覺得很親切。這里目前有500多道題目,難易分配適中,且涵蓋了各大洲的題目類型並配有索引,除此之外,ZOJ的JUDGE系統是幾個網站中表現得比較好的一個,很少出現Wrong Answer和Presentation error混淆的情況。這里每月也辦有一次網上比賽,只要是注冊的用戶都可以參加。

說起中國的ONLINE JUDGE,去年才開始參加ACM競賽的北京大學現在也建立了自己的提交系統;而我們學校也是去年開始參加比賽,現在也有可能推出自己的提交系統,如果能夠做成,到時候大家就可以去上面做題了。同類網站的飛速發展標志著有越來越多的同學有興趣進入信息學的領域探索,這是一件好事,同時也意味著更激烈的競爭。

看看這篇文章對你有什麼幫助!我也是ACM初學者!

I. C程序的動態規劃是啥意思

【關鍵詞】動態規劃 階段
【摘要】
動態規劃是信息學競賽中的常見演算法,本文的主要內容就是分析它的特點。
文章的第一部分首先探究了動態規劃的本質,因為動態規劃的特點是由它的本質所決定的。第二部分從動態規劃的設計和實現這兩個角度分析了動態規劃的多樣性、模式性、技巧性這三個特點。第三部分將動態規劃和遞推、搜索、網路流這三個相關演算法作了比較,從中探尋動態規劃的一些更深層次的特點。
文章在分析動態規劃的特點的同時,還根據這些特點分析了我們在解題中應該怎樣利用這些特點,怎樣運用動態規劃。這對我們的解題實踐有一定的指導意義。
【正文】
動態規劃是編程解題的一種重要的手段,在如今的信息學競賽中被應用得越來越普遍。最近幾年的信息學競賽,不分大小,幾乎每次都要考察到這方面的內容。因此,如何更深入地了解動態規劃,從而更為有效地運用這個解題的有力武器,是一個值得深入研究的問題。
要掌握動態規劃的應用技巧,就要了解它的各方面的特點。首要的,是要深入洞悉動態規劃的本質。
§1動態規劃的本質
動態規劃是在本世紀50年代初,為了解決一類多階段決策問題而誕生的。那麼,什麼樣的問題被稱作多階段決策問題呢?
§1.1多階段決策問題
說到多階段決策問題,人們很容易舉出下面這個例子。
[例1] 多段圖中的最短路徑問題:在下圖中找出從A1到D1的最短路徑。
仔細觀察這個圖不難發現,它有一個特點。我們將圖中的點分為四類(圖中的A、B、C、D),那麼圖中所有的邊都處於相鄰的兩類點之間,並且都從前一類點指向後一類點。這樣,圖中的邊就被分成了三類(AàB、BàC、CàD)。我們需要從每一類中選出一條邊來,組成從A1到D1的一條路徑,並且這條路徑是所有這樣的路徑中的最短者。
從上面的這個例子中,我們可以大概地了解到什麼是多階段決策問題。更精確的定義如下:
多階段決策過程,是指這樣的一類特殊的活動過程,問題可以按時間順序分解成若干相互聯系的階段,在每一個階段都要做出決策,全部過程的決策是一個決策序列[1]。要使整個活動的總體效果達到最優的問題,稱為多階段決策問題。
從上述的定義中,我們可以明顯地看出,這類問題有兩個要素。一個是階段,一個是決策。
§1.2階段與狀態
階段:將所給問題的過程,按時間或空間特徵分解成若干相互聯系的階段,以便按次序去求每階段的解。常用字母k表示階段變數。[1]
階段是問題的屬性。多階段決策問題中通常存在著若干個階段,如上面的例子,就有A、B、C、D這四個階段。在一般情況下,階段是和時間有關的;但是在很多問題(我的感覺,特別是信息學問題)中,階段和時間是無關的。從階段的定義中,可以看出階段的兩個特點,一是「相互聯系」,二是「次序」。
階段之間是怎樣相互聯系的?就是通過狀態和狀態轉移。
狀態:各階段開始時的客觀條件叫做狀態。描述各階段狀態的變數稱為狀態變數,常用sk表示第k階段的狀態變數,狀態變數sk的取值集合稱為狀態集合,用Sk表示。[1]
狀態是階段的屬性。每個階段通常包含若干個狀態,用以描述問題發展到這個階段時所處在的一種客觀情況。在上面的例子中,行人從出發點A1走過兩個階段之後,可能出現的情況有三種,即處於C1、C2或C3點。那麼第三個階段就有三個狀態S3={C1,C2,C3}。
每個階段的狀態都是由以前階段的狀態以某種方式「變化」而來,這種「變化」稱為狀態轉移(暫不定義)。上例中C3點可以從B1點過來,也可以從B2點過來,從階段2的B1或B2狀態走到階段3的C3狀態就是狀態轉移。狀態轉移是導出狀態的途徑,也是聯系各階段的途徑。
說到這里,可以提出應用動態規劃的一個重要條件。那就是將各階段按照一定的次序排列好之後,對於某個給定的階段狀態,它以前各階段的狀態無法直接影響它未來的發展,而只能通過當前的這個狀態。換句話說,每個狀態都是「過去歷史的一個完整總結[1]」。這就是無後效性。對這個性質,下文還將會有解釋。
§1.3決策和策略
上面的階段與狀態只是多階段決策問題的一個方面的要素,下面是另一個方面的要素——決策。
決策:當各段的狀態取定以後,就可以做出不同的決定,從而確定下一階段的狀態,這種決定稱為決策。表示決策的變數,稱為決策變數,常用uk(sk)表示第k階段當狀態為sk時的決策變數。在實際問題中,決策變數的取值往往限制在一定范圍內,我們稱此范圍為允許決策集合。常用Dk(sk)表示第k階段從狀態sk出發的允許決策集合。顯然有uk(sk) ÎDk(sk)。[1]
決策是問題的解的屬性。決策的目的就是「確定下一階段的狀態」,還是回到上例,從階段2的B1狀態出發有三條路,也就是三個決策,分別導向階段3的C1、C2、C3三個狀態,即D2(B1)={C1,C2,C3}。
有了決策,我們可以定義狀態轉移:動態規劃中本階段的狀態往往是上一階段和上一階段的決策結果,由第k段的狀態sk和本階段的決策uk確定第k+1段的狀態sk+1的過程叫狀態轉移。狀態轉移規律的形式化表示sk+1=Tk(sk,uk)稱為狀態轉移方程。
這樣看來,似乎決策和狀態轉移有著某種聯系。我的理解,狀態轉移是決策的目的,決策是狀態轉移的途徑。
各段決策確定後,整個問題的決策序列就構成一個策略,用p1,n={u1(s1),u2(s2),…, un(sn)}表示。對每個實際問題,可供選擇的策略有一定范圍,稱為允許策略集合,記作P1,n,使整個問題達到最有效果的策略就是最優策略。[1]
說到這里,又可以提出運用動態規劃的一個前提。即這個過程的最優策略應具有這樣的性質:無論初始狀態及初始決策如何,對於先前決策所形成的狀態而言,其以後的所有決策應構成最優策略[1]。這就是最優化原理。簡言之,就是「最優策略的子策略也是最優策略」。
§1.4最優化原理與無後效性
這里,我把最優化原理定位在「運用動態規劃的前提」。這是因為,是否符合最優化原理是一個問題的本質特徵。對於不滿足最優化原理的一個多階段決策問題,整體上的最優策略p1,n同任何一個階段k上的決策uk或任何一組階段k1…k2上的子策略pk1,k2都不存在任何關系。如果要對這樣的問題動態規劃的話,我們從一開始所作的劃分階段等努力都將是徒勞的。
而我把無後效性定位在「應用動態規劃的條件」,是因為動態規劃是按次序去求每階段的解,如果一個問題有後效性,那麼這樣的次序便是不合理的。但是,我們可以通過重新劃分階段,重新選定狀態,或者增加狀態變數的個數等手段,來是問題滿足無後效性這個條件。說到底,還是要確定一個「序」。
在信息學的多階段決策問題中,絕大部分都是能夠滿足最優化原理的,但它們往往會在後效性這一點上來設置障礙。所以在解題過程中,我們會特別關心「序」。對於有序的問題,就會考慮到動態規劃;對於無序的問題,也會想方設法來使其有序。
§1.5最優指標函數和規劃方程
最優指標函數:用於衡量所選定策略優劣的數量指標稱為指標函數,最優指標函數記為fk(sk),它表示從第k段狀態sk採用最優策略p*k,n到過程終止時的最佳效益值[1]。
最優指標函數其實就是我們真正關心的問題的解。在上面的例子中,f2(B1)就表示從B1點到終點D1點的最短路徑長度。我們求解的最終目標就是f1(A1)。
最優指標函數的求法一般是一個從目標狀態出發的遞推公式,稱為規劃方程:

其中sk是第k段的某個狀態,uk是從sk出發的允許決策集合Dk(sk)中的一個決策,Tk(sk,uk)是由sk和uk所導出的第k+1段的某個狀態sk+1,g(x,uk)是定義在數值x和決策uk上的一個函數,而函數opt表示最優化,根據具體問題分別表為max或min。
,稱為邊界條件。
上例中的規劃方程就是:

邊界條件為
這里是一種從目標狀態往回推的逆序求法,適用於目標狀態確定的問題。在我們的信息學問題中,也有很多有著確定的初始狀態。當然,對於初始狀態確定的問題,我們也可以採用從初始狀態出發往前推的順序求法。事實上,這種方法對我們來說要更為直觀、更易設計一些,從而更多地出現在我們的解題過程中。
我們本節所討論的這些理論雖然不是本文的主旨,但是卻對下面要說的動態規劃的特點起著基礎性的作用。
§2動態規劃的設計與實現
上面我們討論了動態規劃的一些理論,本節我們將通過幾個例子中,動態規劃的設計與實現,來了解動態規劃的一些特點。
§2.1動態規劃的多樣性
[例2] 花店櫥窗布置問題(IOI99)試題見附錄
本題雖然是本屆IOI中較為簡單的一題,但其中大有文章可作。說它簡單,是因為它有序,因此我們一眼便可看出這題應該用動態規劃來解決。但是,如何動態規劃呢?如何劃分階段,又如何選擇狀態呢?
<方法1>以花束的數目來劃分階段。在這里,階段變數k表示的就是要布置的花束數目(前k束花),狀態變數sk表示第k束花所在的花瓶。而對於每一個狀態sk,決策就是第k-1束花應該放在哪個花瓶,用uk表示。最優指標函數fk(sk)表示前k束花,其中第k束插在第sk個花瓶中,所能取得的最大美學值。
狀態轉移方程為
規劃方程為
(其中A(i,j)是花束i插在花瓶j中的美學值)
邊界條件 (V是花瓶總數,事實上這是一個虛擬的邊界)
<方法2>以花瓶的數目來劃分階段。在這里階段變數k表示的是要佔用的花瓶數目(前k個花瓶),狀態變數sk表示前k個花瓶中放了多少花。而對於任意一個狀態sk,決策就是第sk束花是否放在第k個花瓶中,用變數uk=1或0來表示。最優指標函數fk(sk)表示前k個花瓶中插了sk束花,所能取得的最大美學值。
狀態轉移方程為
規劃方程為
邊界條件為
兩種劃分階段的方法,引出了兩種狀態表示法,兩種規劃方式,但是卻都成功地解決了問題。只不過因為決策的選擇有多有少,所以演算法的時間復雜度也就不同。[2]
這個例子具有很大的普遍性。有很多的多階段決策問題都有著不止一種的階段劃分方法,因而往往就有不止一種的規劃方法。有時各種方法所產生的效果是差不多的,但更多的時候,就像我們的例子一樣,兩種方法會在某個方面有些區別。
所以,在用動態規劃解題的時候,可以多想一想是否有其它的解法。對於不同的解法,要注意比較,好的演算法好在哪裡,差一點的演算法差在哪裡。從各種不同演算法的比較中,我們可以更深刻地領會動態規劃的構思技巧。
§2.2動態規劃的模式性
這個可能做過動態規劃的人都有體會,從我們上面對動態規劃的分析也可以看出來。動態規劃的設計都有著一定的模式,一般要經歷以下幾個步驟。
劃分階段:按照問題的時間或空間特徵,把問題分為若干個階段。注意這若干個階段一定要是有序的或者是可排序的,否則問題就無法求解。
選擇狀態:將問題發展到各個階段時所處於的各種客觀情況用不同的狀態表示出來。當然,狀態的選擇要滿足無後效性。
確定決策並寫出狀態轉移方程:之所以把這兩步放在一起,是因為決策和狀態轉移有著天然的聯系,狀態轉移就是根據上一階段的狀態和決策來導出本階段的狀態。所以,如果我們確定了決策,狀態轉移方程也就寫出來了。但事實上,我們常常是反過來做,根據相鄰兩段的各狀態之間的關系來確定決策。
寫出規劃方程(包括邊界條件):在第一部分中,我們已經給出了規劃方程的通用形式化表達式。一般說來,只要階段、狀態、決策和狀態轉移確定了,這一步還是比較簡單的。
動態規劃的主要難點在於理論上的設計,一旦設計完成,實現部分就會非常簡單。大體上的框架如下:
對f1(s1)初始化(邊界條件)
for kß2 to n(這里以順序求解為例)
對每一個skÎSk
fk(sk)ß一個極值(∞或-∞)
對每一個uk(sk)ÎDk(sk)
sk-1ßTk(sk,uk)
tßg(fk-1(sk-1),uk)
y t比fk(sk)更優 n
fk(sk)ßt
輸出fn(sn)
這個N-S圖雖然不能代表全部,但足可以概括大多數。少數的一些特殊的動態規劃,其實現的原理也是類似,可以類比出來。我們到現在對動態規劃的分析,主要是在理論上、設計上,原因也就在此。
掌握了動態規劃的模式性,我們在用動態規劃解題時就可以把主要的精力放在理論上的設計。一旦設計成熟,問題也就基本上解決了。而且在設計演算法時也可以按部就班地來。
但是「物極必反」,太過拘泥於模式就會限制我們的思維,扼殺優良演算法思想的產生。我們在解題時,不妨發揮一下創造性,去突破動態規劃的實現模式,這樣往往會收到意想不到的效果。[3]
§2.3動態規劃的技巧性
上面我們所說的動態規劃的模式性,主要指的是實現方面。而在設計方面,雖然它較為嚴格的步驟性,但是它的設計思想卻是沒有一定的規律可循的。這就需要我們不斷地在實踐當中去掌握動態規劃的技巧,下面僅就一個例子談一點我自己的體會。
[例3] 街道問題:在下圖中找出從左下角到右上角的最短路徑,每步只能向右方或上方走。
這是一道簡單而又典型的動態規劃題,許多介紹動態規劃的書與文章中都拿它來做例子。通常,書上的解答是這樣的:

按照圖中的虛線來劃分階段,即階段變數k表示走過的步數,而狀態變數sk表示當前處於這一階段上的哪一點(各點所對應的階段和狀態已經用ks在地圖上標明)。這時的模型實際上已經轉化成了一個特殊的多段圖。用決策變數uk=0表示向右走,uk=1表示向上走,則狀態轉移方程如下:

(這里的row是地圖豎直方向的行數)
我們看到,這個狀態轉移方程需要根據k的取值分兩種情況討論,顯得非常麻煩。相應的,把它代入規劃方程而付諸實現時,演算法也很繁。因而我們在實現時,一般是不會這么做的,而代之以下面方法:
將地圖中的點規則地編號如上,得到的規劃方程如下:

(這里Distance表示相鄰兩點間的邊長)
這樣做確實要比上面的方法簡單多了,但是它已經破壞了動態規劃的本來面目,而不存在明確的階段特徵了。如果說這種方法是以地圖中的行(A、B、C、D)來劃分階段的話,那麼它的「狀態轉移」就不全是在兩個階段之間進行的了。
也許這沒什麼大不了的,因為實踐比理論更有說服力。但是,如果我們把題目擴展一下:在地圖中找出從左下角到右上角的兩條路徑,兩條路徑中的任何一條邊都不能重疊,並且要求兩條路徑的總長度最短。這時,再用這種「簡單」的方法就不太好辦了。
如果非得套用這種方法的話,則最優指標函數就需要有四維的下標,並且難以處理兩條路徑「不能重疊」的問題。
而我們回到原先「標准」的動態規劃法,就會發現這個問題很好解決,只需要加一維狀態變數就成了。即用sk=(ak,bk)分別表示兩條路徑走到階段k時所處的位置,相應的,決策變數也增加一維,用uk=(xk,yk)分別表示兩條路徑的行走方向。狀態轉移時將兩條路徑分別考慮:

在寫規劃方程時,只要對兩條路徑走到同一個點的情況稍微處理一下,減少可選的決策個數:

從這個例子中可以總結出設計動態規劃演算法的一個技巧:狀態轉移一般是在相鄰的兩個階段之間(有時也可以在不相鄰的兩個階段間),但是盡量不要在同一個階段內進行。
動態規劃是一種很靈活的解題方法,在動態規劃演算法的設計中,類似的技巧還有很多。要掌握動態規劃的技巧,有兩條途徑:一是要深刻理解動態規劃的本質,這也是我們為什麼一開始就探討它的本質的原因;二是要多實踐,不但要多解題,還要學會從解題中探尋規律,總結技巧。
§3動態規劃與一些演算法的比較
動態規劃作為諸多解題方法中的一種,必然和其他一些演算法有著諸多聯系。從這些聯系中,我們也可以看出動態規劃的一些特點。
§3.1動態規劃與遞推
——動態規劃是最優化演算法
由於動態規劃的「名氣」如此之大,以至於很多人甚至一些資料書上都往往把一種與動態規劃十分相似的演算法,當作是動態規劃。這種演算法就是遞推。實際上,這兩種演算法還是很容易區分的。
按解題的目標來分,信息學試題主要分四類:判定性問題、構造性問題、計數問題和最優化問題。我們在競賽中碰到的大多是最優化問題,而動態規劃正是解決最優化問題的有力武器,因此動態規劃在競賽中的地位日益提高。而遞推法在處理判定性問題和計數問題方面也是一把利器。下面分別就兩個例子,談一下遞推法和動態規劃在這兩個方面的聯系。
[例4] mod 4 最優路徑問題:在下圖中找出從第1點到第4點的一條路徑,要求路徑長度mod 4的余數最小。
這個圖是一個多段圖,而且是一個特殊的多段圖。雖然這個圖的形式比一般的多段圖要簡單,但是這個最優路徑問題卻不能用動態規劃來做。因為一條從第1點到第4點的最優路徑,在它走到第2點、第3點時,路徑長度mod 4的余數不一定是最小,也就是說最優策略的子策略不一定最優——這個問題不滿足最優化原理。
但是我們可以把它轉換成判定性問題,用遞推法來解決。判斷從第1點到第k點的長度mod 4為sk的路徑是否存在,用fk(sk)來表示,則遞推公式如下:
(邊界條件)

(這里lenk,i表示從第k-1點到第k點之間的第i條邊的長度,方括弧表示「或(or)」運算)
最後的結果就是可以使f4(s4)值為真的最小的s4值。
這個遞推法的遞推公式和動態規劃的規劃方程非常相似,我們在這里借用了動態規劃的符號也就是為了更清楚地顯示這一點。其實它們的思想也是非常相像的,可以說是遞推法借用了動態規劃的思想解決了動態規劃不能解決的問題。
有的多階段決策問題(像這一題的階段特徵就很明顯),由於不能滿足最優化原理等使用動態規劃的先決條件,而無法應用動態規劃。在這時可以將最優指標函數的值當作「狀態」放到下標中去,從而變最優化問題為判定性問題,再借用動態規劃的思想,用遞推法來解決問題。
§3.2動態規劃與搜索
——動態規劃是高效率、高消費演算法
同樣是解決最優化問題,有的題目我們採用動態規劃,而有的題目我們則需要用搜索。這其中有沒有什麼規則呢?
我們知道,撇開時空效率的因素不談,在解決最優化問題的演算法中,搜索可以說是「萬能」的。所以動態規劃可以解決的問題,搜索也一定可以解決。
把一個動態規劃演算法改寫成搜索是非常方便的,狀態轉移方程、規劃方程以及邊界條件都可以直接「移植」,所不同的只是求解順序。動態規劃是自底向上的遞推求解,而搜索則是自頂向下的遞歸求解(這里指深度搜索,寬度搜索類似)。
反過來,我們也可以把搜索演算法改寫成動態規劃。狀態空間搜索實際上是對隱式圖中的點進行枚舉,這種枚舉是自頂向下的。如果把枚舉的順序反過來,變成自底向上,那麼就成了動態規劃。(當然這里有個條件,即隱式圖中的點是可排序的,詳見下一節。)
正因為動態規劃和搜索有著求解順序上的不同,這也造成了它們時間效率上的差別。在搜索中,往往會出現下面的情況:
對於上圖(a)這樣幾個狀態構成的一個隱式圖,用搜索演算法就會出現重復,如上圖(b)所示,狀態C2被搜索了兩次。在深度搜索中,這樣的重復會引起以C2為根整個的整個子搜索樹的重復搜索;在寬度搜索中,雖然這樣的重復可以立即被排除,但是其時間代價也是不小的。而動態規劃就沒有這個問題,如上圖(c)所示。
一般說來,動態規劃演算法在時間效率上的優勢是搜索無法比擬的。(當然對於某些題目,根本不會出現狀態的重復,這樣搜索和動態規劃的速度就沒有差別了。)而從理論上講,任何拓撲有序(現實中這個條件常常可以滿足)的隱式圖中的搜索演算法都可以改寫成動態規劃。但事實上,在很多情況下我們仍然不得不採用搜索演算法。那麼,動態規劃演算法在實現上還有什麼障礙嗎?
考慮上圖(a)所示的隱式圖,其中存在兩個從初始狀態無法達到的狀態。在搜索演算法中,這樣的兩個狀態就不被考慮了,如上圖(b)所示。但是動態規劃由於是自底向上求解,所以就無法估計到這一點,因而遍歷了全部的狀態,如上圖(c)所示。
一般說來,動態規劃總要遍歷所有的狀態,而搜索可以排除一些無效狀態。更重要的事搜索還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。
如何協調好動態規劃的高效率與高消費之間的矛盾呢?有一種折衷的辦法就是記憶化演算法。記憶化演算法在求解的時候還是按著自頂向下的順序,但是每求解一個狀態,就將它的解保存下來,以後再次遇到這個狀態的時候,就不必重新求解了。這種方法綜合了搜索和動態規劃兩方面的優點,因而還是很有實用價值的。
§3.3動態規劃與網路流
——動態規劃是易設計易實現演算法
由於圖的關系復雜而無序,一般難以呈現階段特徵(除了特殊的圖如多段圖,或特殊的分段方法如Floyd),因此動態規劃在圖論中的應用不多。但有一類圖,它的點卻是有序的,這就是有向無環圖。
在有向無環圖中,我們可以對點進行拓撲排序,使其體現出有序的特徵,從而據此劃分階段。在有向無還圖中求最短路徑的演算法[4],已經體現出了簡單的動態規劃思想。但動態規劃在圖論中還有更有價值的應用。下面先看一個例子。
[例6] N個人的街道問題:在街道問題(參見例3)中,若有N個人要從左下角走向右上角,要求他們走過的邊的總長度最大。當然,這里每個人也只能向右或向上走。下面是一個樣例,左圖是從出發地到目的地的三條路徑,右圖是他們所走過的邊,這些邊的總長度為5 + 4 + 3 + 6 + 3 + 3 + 5 + 8 + 8 + 7 + 4 + 5 + 9 + 5 + 3 = 78(不一定是最大)。
這個題目是對街道問題的又一次擴展。仿照街道問題的解題方法,我們仍然可以用動態規劃來解決本題。不過這一次是N個人同時走,狀態變數也就需要用N維來表示,。相應的,決策變數也要變成N維,uk=(uk,1,uk,2,…,uk,N)。狀態轉移方程不需要做什麼改動:

在寫規劃方程時,需要注意在第k階段,N條路徑所走過的邊的總長度的計算,在這里我就用gk(sk,uk)來表示了:

邊界條件為
可見將原來的動態規劃演算法移植到這個問題上來,在理論上還是完全可行的。但是,現在的這個動態規劃演算法的時空復雜度已經是關於N的指數函數,只要N稍微大一點,這個演算法就不可能實現了。
下面我們換一個思路,將N條路徑看成是網路中一個流量為N的流,這樣求解的目標就是使這個流的費用最大。但是本題又不同於一般的費用流問題,在每一條邊e上的流費用並不是流量和邊權的乘積 ,而是用下式計算:

為了使經典的費用流演算法適用於本題,我們需要將模型稍微轉化一下:
如圖,將每條邊拆成兩條。拆開後一條邊上有權,但是容量限制為1;另一條邊沒有容量限制,但是流過這條邊就不能計算費用了。這樣我們就把問題轉化成了一個標準的最大費用固定流問題。
這個演算法可以套用經典的最小費用最大流演算法,在此就不細說了。(參見附錄中的源程序)
這個例題是我仿照IOI97的「障礙物探測器」一題[6]編出來的。「障礙物探測器」比這一題要復雜一些,但是基本思想是相似的。類似的題目還有99年冬令營的「迷宮改造」[7]。從這些題目中都可以看到動態規劃和網路流的聯系。
推廣到一般情況,任何有向無環圖中的費用流問題在理論上說,都可以用動態規劃來解決。對於流量為N(如果流量不固定,這個N需要事先求出來)的費用流問題,用N維的變數sk=(sk,1,sk,2,…,sk,N)來描述狀態,其中sk,iÎV(1£i£N)。相應的,決策也用N維的變數uk=(uk,1,uk,2,…,uk,N)來表示,其中uk,iÎE(sk,i)(1£i£N),E(v)表示指向v的弧集。則狀態轉移方程可以這樣表示:
sk-1,i = uk,i的弧尾結點
規劃方程為
邊界條件為
但是,由於動態規劃演算法是指數級演算法,因而在實現中的局限性很大,僅可用於一些N非常小的題目。然而在競賽解題中,比如上面說到的IOI97以及99冬令營測試時,我們使用動態規劃的傾向性很明顯(「障礙物探測器」中,我們用的是貪心策略,求N=1或N=2時的局部最優解[8])。這主要有兩個原因:
一. 雖然網路流有著經典的演算法,但是在競賽中不可能出現經典的問題。如果要運用網路流演算法,則需要經過一番模型轉化,有時這個轉化還是相當困難的。因此在演算法的設計上,靈活巧妙的動態規劃演算法反而要更為簡單一些。
二. 網路流演算法實現起來很繁,這是被人們公認的。因而在競賽的緊張環境中,實現起來有一定模式的動態規劃演算法又多了一層優勢。
正由於動態規劃演算法在設計和實現上的簡便性,所以在N不太大時,也就是在動態規劃可行的情況下,我們還是應該盡量運用動態規劃。
§4結語
本文的內容比較雜,是我幾年來對動態規劃的參悟理解、心得體會。雖然主要的篇幅講的都是理論,但是根本的目的還是指導實踐。
動態規劃,據我認為,是當今信息學競賽中最靈活、也最能體現解題者水平的一類解題方法。本文內容雖多,不能涵蓋動態規劃之萬一。「紙上得來終覺淺,絕知此事要躬行。」要想真正領悟、理解動態規劃的思想,掌握動態規劃的解題技巧,還需要在實踐中不斷地挖掘、探索。實踐得多了,也就能體會到漸入佳境之妙了。

閱讀全文

與演算法集訓隊作用相關的資料

熱點內容
電影邪惡 瀏覽:895
爸爸出海之罪孽泰國免費 瀏覽:201
比較推薦的看片網站 瀏覽:80
一個老頭淘金的電影 瀏覽:175
誰還有看片網址 瀏覽:184
熊:出 瀏覽:176
阿里程序員不加班離職 瀏覽:45
六級pdf 瀏覽:855
jsp嵌入java代碼 瀏覽:162
Python中Windows字體顏色 瀏覽:693
n7筆記app哪個好 瀏覽:416
kindle用什麼app好 瀏覽:720
方舟加密伺服器怎麼進 瀏覽:61
傳文件夾太慢 瀏覽:219
基於單片機的倉庫 瀏覽:378
央企直營朔源碼燕窩 瀏覽:341
日本校園老師電影 瀏覽:65
買黃金首飾上什麼app 瀏覽:452
共享pdf 瀏覽:343
老武俠電影,是一個女的用乳房打人,名字 瀏覽:650