ACM學習計劃

ACM學習建議 php

 

一位高手對個人建議: html

 

通常要作到50行之內的程序不用調試、100行之內的二分鐘內調試成功.acm主要是考算法的 node

,主要時間是花在思考算法上,不是花在寫程序與debug上。 ios

下面給個計劃你練練: 算法

 

第一階段: 編程

練經典經常使用算法,下面的每一個算法給我打上十到二十遍,同時本身精簡代碼, 數組

由於太經常使用,因此要練到寫時不用想,10-15分鐘內打完,甚相當掉顯示器均可以把程序打 服務器

出來. 網絡

1.最短路(Floyd、Dijstra,BellmanFord) 數據結構

2.最小生成樹(先寫個prim,kruscal要用並查集,很差寫)

3.大數(高精度)加減乘除

4.二分查找. (代碼可在五行之內)

5.叉乘、判線段相交、而後寫個凸包.

6.BFS、DFS,同時熟練hash表(要熟,要靈活,代碼要簡)

7.數學上的有:展轉相除(兩行內),線段交點、多角形面積公式.

8. 調用系統的qsort, 技巧不少,慢慢掌握.

9. 任意進制間的轉換

 

 

第二階段:

練習複雜一點,但也較經常使用的算法。

如:

1. 二分圖匹配(匈牙利),最小路徑覆蓋

2. 網絡流,最小費用流。

3. 線段樹.

4. 並查集。

5. 熟悉動態規劃的各個典型:LCS、最長遞增子串、三角剖分、記憶化dp

6.博弈類算法。博弈樹,二進制法等。

7.最大團,最大獨立集。

8.判斷點在多邊形內。

9. 差分約束系統.

10. 雙向廣度搜索、A*算法,最小耗散優先.

 

 

第三階段:

前兩個階段是打基礎,第三階段是鍛鍊在比賽中能夠快速創建模型、想新算法

。這就要平時多作作綜合的題型了。

1. 把oibh上的論文看看(大概幾百篇的,我只看了一點點,呵呵)。

2. 平時掃掃zoj上的難題啦,別老作那些不用想的題.(中大acm的版主常常說我挑簡單的來

作:-P )

3. 多參加網上的比賽,感覺一下比賽的氣氛,評估本身的實力.

4. 一道題不要過了就算,問一下人,有更好的算法也打一下。

5. 作過的題要記好 :-)

 

 

ACM ICPC學習計劃

 

大牛給的計劃——

通常要作到50行之內的程序不用調試、100行之內的二分鐘內調試成功.acm主要是考算法的,主要時間是花在思考算法上,不是花在寫程序與debug上。

下面給個計劃你練練:

第一階段:練經典經常使用算法,下面的每一個算法給我打上十到二十遍,同時本身精簡代碼,

由於太經常使用,因此要練到寫時不用想,10-15分鐘內打完,甚相當掉顯示器均可以把程序打

出來.

1.最短路(Floyd、Dijstra,BellmanFord)

2.最小生成樹(先寫個prim,kruscal要用並查集,很差寫)

3.大數(高精度)加減乘除

4.二分查找. (代碼可在五行之內)

5.叉乘、判線段相交、而後寫個凸包.

6.BFS、DFS,同時熟練hash表(要熟,要靈活,代碼要簡)

7.數學上的有:展轉相除(兩行內),線段交點、多角形面積公式.

8. 調用系統的qsort, 技巧不少,慢慢掌握.

9. 任意進制間的轉換

第二階段:練習複雜一點,但也較經常使用的算法。

如:

1. 二分圖匹配(匈牙利),最小路徑覆蓋

2. 網絡流,最小費用流。

3. 線段樹.

4. 並查集。

5. 熟悉動態規劃的各個典型:LCS、最長遞增子串、三角剖分、記憶化dp

6.博弈類算法。博弈樹,二進制法等。

7.最大團,最大獨立集。

8.判斷點在多邊形內。

9. 差分約束系統.

10. 雙向廣度搜索、A*算法,最小耗散優先.

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

ACMer必備知識(這麼多呀,慢慢學了……

 

圖論

 

 

 

路徑問題

 

0/1邊權最短路徑

 

BFS

 

非負邊權最短路徑(Dijkstra)

 

能夠用Dijkstra解決問題的特徵

 

負邊權最短路徑

 

Bellman-Ford

 

Bellman-Ford的Yen-氏優化

 

差分約束系統

 

Floyd

 

廣義路徑問題

 

傳遞閉包

 

極小極大距離 / 極大極小距離

 

Euler Path / Tour

 

圈套圈算法

 

混合圖的 Euler Path / Tour

 

Hamilton Path / Tour

 

特殊圖的Hamilton Path / Tour 構造

 

 

 

生成樹問題

 

最小生成樹

 

第k小生成樹

 

最優比率生成樹

 

0/1分數規劃

 

度限制生成樹

 

 

 

連通性問題

 

強大的DFS算法

 

無向圖連通性

 

割點

 

割邊

 

二連通分支

 

有向圖連通性

 

強連通分支

 

2-SAT

 

最小點基

 

 

 

有向無環圖

 

拓撲排序

 

有向無環圖與動態規劃的關係

 

 

 

二分圖匹配問題

 

通常圖問題與二分圖問題的轉換思路

 

最大匹配

 

有向圖的最小路徑覆蓋

 

0 / 1矩陣的最小覆蓋

 

完備匹配

 

最優匹配

 

穩定婚姻

 

 

 

網絡流問題

 

網絡流模型的簡單特徵和與線性規劃的關係

 

最大流最小割定理

 

最大流問題

 

有上下界的最大流問題

 

循環流

 

最小費用最大流 / 最大費用最大流

 

 

 

弦圖的性質和斷定

 

 

 

 

 

組合數學

 

 

 

解決組合數學問題時經常使用的思想

 

逼近

 

遞推 / 動態規劃

 

機率問題

 

Polya定理

 

 

 

 

 

計算幾何 / 解析幾何

 

 

 

計算幾何的核心:叉積 / 面積

 

解析幾何的主力:複數

 

 

 

基本形

 

 

直線,線段

 

多邊形

 

 

 

凸多邊形 / 凸包

 

凸包算法的引進,捲包裹法

 

 

 

Graham掃描法

 

水平序的引進,共線凸包的補丁

 

 

 

完美凸包算法

 

 

 

相關斷定

 

兩直線相交

 

兩線段相交

 

點在任意多邊形內的斷定

 

點在凸多邊形內的斷定

 

 

 

經典問題

 

最小外接圓

 

近似O(n)的最小外接圓算法

 

點集直徑

 

旋轉卡殼,對踵點

 

多邊形的三角剖分

 

 

 

 

 

數學 / 數論

 

 

 

最大公約數

 

Euclid算法

 

擴展的Euclid算法

 

同餘方程 / 二元一次不定方程

 

同餘方程組

 

 

 

線性方程組

 

高斯消元法

 

解mod 2域上的線性方程組

 

整係數方程組的精確解法

 

 

 

矩陣

 

行列式的計算

 

利用矩陣乘法快速計算遞推關係

 

 

 

分數

 

分數樹

 

連分數逼近

 

 

 

數論計算

 

求N的約數個數

 

求phi(N)

 

求約數和

 

快速數論變換

 

……

 

 

 

素數問題

 

機率判素算法

 

機率因子分解

 

 

 

 

 

數據結構

 

 

 

組織結構

 

二叉堆

 

左偏樹

 

二項樹

 

勝者樹

 

跳躍表

 

樣式圖標

 

斜堆

 

reap

 

 

 

統計結構

 

樹狀數組

 

虛二叉樹

 

線段樹

 

矩形面積並

 

圓形面積並

 

 

 

關係結構

 

Hash表

 

並查集

 

路徑壓縮思想的應用

 

 

 

STL中的數據結構

 

vector

 

deque

 

set / map

 

 

 

 

 

動態規劃 / 記憶化搜索

 

 

 

動態規劃和記憶化搜索在思考方式上的區別

 

 

 

最長子序列系列問題

 

最長不降低子序列

 

最長公共子序列

 

最長公共不降低子序列

 

 

 

一類NP問題的動態規劃解法

 

 

 

樹型動態規劃

 

 

 

揹包問題

 

 

 

動態規劃的優化

 

四邊形不等式

 

函數的凸凹性

 

狀態設計

 

規劃方向

 

 

 

 

 

線性規劃

 

 

 

經常使用思想

 

 

 

二分

 

最小表示法

 

 

 

 

 

 

KMP

 

Trie結構

 

後綴樹/後綴數組

 

LCA/RMQ

 

有限狀態自動機理論

 

 

 

排序

 

選擇/冒泡

 

快速排序

 

堆排序

 

歸併排序

 

基數排序

 

拓撲排序

 

排序網絡

 

 

熟練掌握數據結構、經常使用算法匯聚

 

 

 

(一)

 

不可能都徹底記住那麼多的算法.

經常使用算法,拿過來就能夠寫出來

不經常使用的,拿起書來,看10分鐘,就能理解算法(由於之前記過).

對之前沒有記過的算法,就很差說了,難的可能要研究好幾天.

這樣就能夠了.

 

應該熟練掌握的經常使用的算法應該有:

各類排序算法(插入排序、冒泡排序、選擇排序,快速排序,堆排序,歸併排序)

線性表(通常的線性表,棧,隊列)的插入和刪除

二叉樹的遍歷(前序,中序,後序)

圖的遍歷(深度優先,廣度優先)

二分法查找,排序二叉樹,Hash查找(處理衝突的方法)。

 

 

(二)

 

分析一個東西,你能夠用不一樣的眼光去看待,有不少時候,就跟本身生活同樣,以爲小時候看待問題很幼稚,如今看問題全面了,並且方式不同了,爲何,就是成長吧,就跟這個同樣的,你對算法,好比寫一個程序,可能直接寫很簡單,但是能夠有一些有趣的方式,好比經過什麼樣來表達,怎麼樣更高效..等等吧

 

 

 

(三)

 

 

 

於大學裏把基本的專業課學紮實就ok,如:數據結構,離散,操做系統等。碰到一些基本的數據結構和算法,如查找排序要根據原理立刻能寫出相應的代碼就好了,我我的是這樣理解的,對於更深層次的東西,也是創建在本身熟練的基礎之上的吧

 

 

 

(四)

 

算法與數據結構考驗試題精析》第2版 機械工業出版社

若是你想練習的話,這裏有N多的題能夠來練習,但實際中能用到的比較少,除非搞一些高端的玩意,不過平時也能夠在本身的項目中結合使用

 

 

 

(五)

 

 

 

數據結構在平時可能用不上,但數據結構能夠培養你程序時若是注意效率的意識,一個學過數據結構的人和一個沒有學過數結構的人寫出來的程序可能在效率上有差異。

 

 

 

(六)

 

搞ACM須要的掌握的算法.

要注意,ACM的競賽性強,所以本身應該和本身的實際應用聯繫起來.

適合本身的纔是好的,有的人不適合搞算法,喜歡系統架構,所以不要看到別人什麼就眼紅,

發揮本身的長處,這纔是重要的.

 

 

第一階段:練經典經常使用算法,下面的每一個算法給我打上十到二十遍,同時本身精簡代碼,

由於太經常使用,因此要練到寫時不用想,10-15分鐘內打完,甚相當掉顯示器均可以把程序打

出來.

1.最短路(Floyd、Dijstra,BellmanFord)

2.最小生成樹(先寫個prim,kruscal要用並查集,很差寫)

3.大數(高精度)加減乘除

4.二分查找. (代碼可在五行之內)

5.叉乘、判線段相交、而後寫個凸包.

6.BFS、DFS,同時熟練hash表(要熟,要靈活,代碼要簡)

7.數學上的有:展轉相除(兩行內),線段交點、多角形面積公式.

8. 調用系統的qsort, 技巧不少,慢慢掌握.

9. 任意進制間的轉換

 

第二階段:練習複雜一點,但也較經常使用的算法。

如:

1. 二分圖匹配(匈牙利),最小路徑覆蓋

2. 網絡流,最小費用流。

3. 線段樹.

4. 並查集。

5. 熟悉動態規劃的各個典型:LCS、最長遞增子串、三角剖分、記憶化dp

6.博弈類算法。博弈樹,二進制法等。

7.最大團,最大獨立集。

8.判斷點在多邊形內。

9. 差分約束系統.

10. 雙向廣度搜索、A*算法,最小耗散優先.

 

 

 

相關的知識

 

圖論

 

路徑問題

0/1邊權最短路徑

BFS

非負邊權最短路徑(Dijkstra)

能夠用Dijkstra解決問題的特徵

負邊權最短路徑

Bellman-Ford

Bellman-Ford的Yen-氏優化

差分約束系統

Floyd

廣義路徑問題

傳遞閉包

極小極大距離 / 極大極小距離

Euler Path / Tour

圈套圈算法

混合圖的 Euler Path / Tour

Hamilton Path / Tour

特殊圖的Hamilton Path / Tour 構造

 

生成樹問題

最小生成樹

第k小生成樹

最優比率生成樹

0/1分數規劃

度限制生成樹

 

連通性問題

強大的DFS算法

無向圖連通性

割點

割邊

二連通分支

有向圖連通性

強連通分支

2-SAT

最小點基

 

有向無環圖

拓撲排序

有向無環圖與動態規劃的關係

 

二分圖匹配問題

通常圖問題與二分圖問題的轉換思路

最大匹配

有向圖的最小路徑覆蓋

0 / 1矩陣的最小覆蓋

完備匹配

最優匹配

穩定婚姻

 

網絡流問題

網絡流模型的簡單特徵和與線性規劃的關係

最大流最小割定理

最大流問題

有上下界的最大流問題

循環流

最小費用最大流 / 最大費用最大流

 

弦圖的性質和斷定

 

 

組合數學

 

解決組合數學問題時經常使用的思想

逼近

遞推 / 動態規劃

機率問題

Polya定理

 

 

計算幾何 / 解析幾何

 

計算幾何的核心:叉積 / 面積

解析幾何的主力:複數

 

基本形

直線,線段

多邊形

 

凸多邊形 / 凸包

凸包算法的引進,捲包裹法

 

Graham掃描法

水平序的引進,共線凸包的補丁

 

完美凸包算法

 

相關斷定

兩直線相交

兩線段相交

點在任意多邊形內的斷定

點在凸多邊形內的斷定

 

經典問題

最小外接圓

近似O(n)的最小外接圓算法

點集直徑

旋轉卡殼,對踵點

多邊形的三角剖分

 

 

數學 / 數論

 

最大公約數

Euclid算法

擴展的Euclid算法

同餘方程 / 二元一次不定方程

同餘方程組

 

線性方程組

高斯消元法

解mod 2域上的線性方程組

整係數方程組的精確解法

 

矩陣

行列式的計算

利用矩陣乘法快速計算遞推關係

 

分數

分數樹

連分數逼近

 

數論計算

求N的約數個數

求phi(N)

求約數和

快速數論變換

……

 

素數問題

機率判素算法

機率因子分解

 

 

數據結構

 

組織結構

二叉堆

左偏樹

二項樹

勝者樹

跳躍表

樣式圖標

斜堆

reap

 

統計結構

樹狀數組

虛二叉樹

線段樹

矩形面積並

圓形面積並

 

關係結構

Hash表

並查集

路徑壓縮思想的應用

 

STL中的數據結構

vector

deque

set / map

 

 

動態規劃 / 記憶化搜索

 

動態規劃和記憶化搜索在思考方式上的區別

 

最長子序列系列問題

最長不降低子序列

最長公共子序列

最長公共不降低子序列

 

一類NP問題的動態規劃解法

 

樹型動態規劃

 

揹包問題

 

動態規劃的優化

四邊形不等式

函數的凸凹性

狀態設計

規劃方向

 

 

線性規劃

 

經常使用思想

 

二分 最小表示法

 

 

KMP Trie結構

後綴樹/後綴數組 LCA/RMQ

有限狀態自動機理論

 

排序

選擇/冒泡 快速排序 堆排序 歸併排序

基數排序 拓撲排序 排序網絡

 

 

中級:

一.基本算法:

(1)C++的標準模版庫的應用. (poj3096,poj3007)

(2)較爲複雜的模擬題的訓練(poj3393,poj1472,poj3371,poj1027,poj2706)

二.圖算法:

(1)差分約束系統的創建和求解. (poj1201,poj2983)

(2)最小費用最大流(poj2516,poj2516,poj2195)

(3)雙連通份量(poj2942)

(4)強連通分支及其縮點.(poj2186)

(5)圖的割邊和割點(poj3352)

(6)最小割模型、網絡流規約(poj3308, )

三.數據結構.

(1)線段樹. (poj2528,poj2828,poj2777,poj2886,poj2750)

(2)靜態二叉檢索樹. (poj2482,poj2352)

(3)樹狀樹組(poj1195,poj3321)

(4)RMQ. (poj3264,poj3368)

(5)並查集的高級應用. (poj1703,2492)

(6)KMP算法. (poj1961,poj2406)

四.搜索

(1)最優化剪枝和可行性剪枝

(2)搜索的技巧和優化 (poj3411,poj1724)

(3)記憶化搜索(poj3373,poj1691)

 

五.動態規劃

(1)較爲複雜的動態規劃(如動態規劃解特別的施行商問題等)

(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)

(2)記錄狀態的動態規劃. (POJ3254,poj2411,poj1185)

(3)樹型動態規劃(poj2057,poj1947,poj2486,poj3140)

六.數學

(1)組合數學:

1.容斥原理.

2.抽屜原理.

3.置換羣與Polya定理(poj1286,poj2409,poj3270,poj1026).

4.遞推關係和母函數.

 

(2)數學.

1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)

2.機率問題. (poj3071,poj3440)

3.GCD、擴展的歐幾里德(中國剩餘定理) (poj3101)

(3)計算方法.

1.0/1分數規劃. (poj2976)

2.三分法求解單峯(單谷)的極值.

3.矩陣法(poj3150,poj3422,poj3070)

4.迭代逼近(poj3301)

(4)隨機化算法(poj3318,poj2454)

(5)雜題.

(poj1870,poj3296,poj3286,poj1095)

七.計算幾何學.

(1)座標離散化.

(2)掃描線算法(例如求矩形的面積和周長並,常和線段樹或堆一塊兒使用).

(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)

(3)多邊形的內核(半平面交)(poj3130,poj3335)

(4)幾何工具的綜合應用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)

 

 

高級:

一.基本算法要求:

(1)代碼快速寫成,精簡但不失風格

(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)

(2)保證正確性和高效性. poj3434

二.圖算法:

(1)度限制最小生成樹和第K最短路. (poj1639)

(2)最短路,最小生成樹,二分圖,最大流問題的相關理論(主要是模型創建和求解)

(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446

(3)最優比率生成樹. (poj2728)

(4)最小樹形圖(poj3164)

(5)次小生成樹.

(6)無向圖、有向圖的最小環

三.數據結構.

(1)trie圖的創建和應用. (poj2778)

(2)LCA和RMQ問題(LCA(最近公共祖先問題) 有離線算法(並查集+dfs) 和 在線算法

(RMQ+dfs)).(poj1330)

(3)雙端隊列和它的應用(維護一個單調的隊列,經常在動態規劃中起到優化狀態轉移的

目的). (poj2823)

(4)左偏樹(可合併堆).

(5)後綴樹(很是有用的數據結構,也是賽區考題的熱點).

(poj3415,poj3294)

四.搜索

(1)較麻煩的搜索題目訓練(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)

(2)廣搜的狀態優化:利用M進制數存儲狀態、轉化爲串用hash表判重、按位壓縮存儲狀態、雙向廣搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)

(3)深搜的優化:儘可能用位運算、必定要加剪枝、函數參數儘量少、層數不易過大、能夠考慮雙向搜索或者是輪換搜索、IDA*算法. (poj3131,poj2870,poj2286)

五.動態規劃

(1)須要用數據結構優化的動態規劃.

(poj2754,poj3378,poj3017)

(2)四邊形不等式理論.

(3)較難的狀態DP(poj3133)

六.數學

(1)組合數學.

1.MoBius反演(poj2888,poj2154)

2.偏序關係理論.

(2)博奕論.

1.極大極小過程(poj3317,poj1085)

2.Nim問題.

七.計算幾何學.

(1)半平面求交(poj3384,poj2540)

(2)可視圖的創建(poj2966)

(3)點集最小圓覆蓋.

(4)對踵點(poj2079)

八.綜合題.

(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263)

 

初期:

一.基本算法:

(1)枚舉. (poj1753,poj2965) (2)貪心(poj1328,poj2109,poj2586)

(3)遞歸和分治法. (4)遞推.

(5)構造法.(poj3295) (6)模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)

二.圖算法:

(1)圖的深度優先遍歷和廣度優先遍歷.

(2)最短路徑算法(dijkstra,bellman-ford,floyd,heap+dijkstra)

(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)

(3)最小生成樹算法(prim,kruskal)

(poj1789,poj2485,poj1258,poj3026)

(4)拓撲排序 (poj1094)

(5)二分圖的最大匹配 (匈牙利算法) (poj3041,poj3020)

(6)最大流的增廣路算法(KM算法). (poj1459,poj3436)

三.數據結構.

(1)串 (poj1035,poj3080,poj1936)

(2)排序(快排、歸併排(與逆序數有關)、堆排) (poj2388,poj2299)

(3)簡單並查集的應用.

(4)哈希表和二分查找等高效查找法(數的Hash,串的Hash)

(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)

(5)哈夫曼樹(poj3253)

(6)堆

(7)trie樹(靜態建樹、動態建樹) (poj2513)

四.簡單搜索

(1)深度優先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)

(2)廣度優先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)

(3)簡單搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)

五.動態規劃

(1)揹包問題. (poj1837,poj1276)

(2)型以下表的簡單DP(可參考lrj的書 page149):

1.E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)

2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最長公共子序列)

(poj3176,poj1080,poj1159)

3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最優二分檢索樹問題)

六.數學

(1)組合數學:

1.加法原理和乘法原理.

2.排列組合.

3.遞推關係.

(POJ3252,poj1850,poj1019,poj1942)

(2)數論.

1.素數與整除問題

2.進制位.

3.同餘模運算.

(poj2635, poj3292,poj1845,poj2115)

(3)計算方法.

1.二分法求解單調函數相關知識.(poj3273,poj3258,poj1905,poj3122)

七.計算幾何學.

(1)幾何公式.

(2)叉積和點積的運用(如線段相交的斷定,點到線段的距離等). (poj2031,poj1039)

(3)多邊型的簡單算法(求面積)和相關斷定(點在多邊型內,多邊型是否相交)

(poj1408,poj1584)

(4)凸包. (poj2187,poj1113)

 

(七)

 

 

 

第一階段:練經典經常使用算法,下面的每一個算法給我打上十到二十遍,同時本身精簡代碼,

由於太經常使用,因此要練到寫時不用想,10-15分鐘內打完,甚相當掉顯示器均可以把程序打

出來.

1.最短路(Floyd、Dijstra,BellmanFord)

2.最小生成樹(先寫個prim,kruscal要用並查集,很差寫)

3.大數(高精度)加減乘除

4.二分查找. (代碼可在五行之內)

5.叉乘、判線段相交、而後寫個凸包.

6.BFS、DFS,同時熟練hash表(要熟,要靈活,代碼要簡)

7.數學上的有:展轉相除(兩行內),線段交點、多角形面積公式.

8. 調用系統的qsort, 技巧不少,慢慢掌握.

9. 任意進制間的轉換

 

第二階段:練習複雜一點,但也較經常使用的算法。

如:

1. 二分圖匹配(匈牙利),最小路徑覆蓋

2. 網絡流,最小費用流。

3. 線段樹.

4. 並查集。

5. 熟悉動態規劃的各個典型:LCS、最長遞增子串、三角剖分、記憶化dp

6.博弈類算法。博弈樹,二進制法等。

7.最大團,最大獨立集。

8.判斷點在多邊形內。

9. 差分約束系統.

10. 雙向廣度搜索、A*算法,最小耗散優先.

 

(八)

 

搞實際項目的話基本用不着多少。lss說的那點都已經多了。固然,偶我的以爲,判斷一個問題是否NPC/NPH仍是比較有用的,判是之後就不會把本身的經歷浪費在尋找多項式算法上了。這點acm要用,實際項目偶以爲也有用。

 

acm的話上面貼的那一長串還不夠用。所謂不夠用,第一,指這些就算都會都不會寫錯,不會創建dp模型不會創建圖論模型的話同樣能掛得很慘,這種活的東西不是死作題就能會的。第二,這表還不全。既然圖能夠扯到最優比率生成樹,那博弈的話至少也得扯SG定理,串的話至少也得扯AC自動機(吐槽:不是自動AC機),

 

 

 

(九)補充中。。。。

 

 

 

浙江大學 http://acm.zju.edu.cn 北京大學 http://acm.pku.edu.cn/JudgeOnline

天津大學 http://acm.tju.edu.cn 廈門大學 http://acm.xmu.edu.cn/JudgeOnline

福州大學 http://acm.fzu.edu.cn 華中科技 http://acm.hust.edu.cn/JudgeOnline

寧波理工 http://acm.nit.net.cn 合肥工大 http://acm.tdzl.net:83/JudgeOnline

汕頭大學 http://acm.stu.edu.cn 北大內部 http://ai.pku.cn/JudgeOnline

中國科大 http://acm.ustc.edu.cn 暨南大學 http://202.116.24.78/JudgeOnline

浙江工業 http://acm.zjut.edu.cn 中山大學 http://202.116.77.69/sicily

福建師範 http://acm.fjnu.edu.cn 哈工業大 http://acm.hit.edu.cn/ojs/ojs.php

杭電科大 http://acm.hziee.edu.cn 四川大學 http://acm.scu.edu.cn/soj

哈工程大 http://acm.hrbeu.edu.cn 武漢大學 http://acm.whu.edu.cn/noah

同濟大學 http://acm.tongji.edu.cn 湖南大學 http://acm.hnu.cn:8080/online/?

上海大學 http://pc.shu.edu.cn/openjudge/problemlist.php

蘭州大學 http://acm.sundayclub.cn/JudgeOnline/problemlist

 

 

 

OJ上的一些水題(可用來練手和增長自信)

(poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)

初期:

一.基本算法:

(1)枚舉. (poj1753,poj2965)

(2)貪心(poj1328,poj2109,poj2586)

(3)遞歸和分治法.

(4)遞推.

(5)構造法.(poj3295)

(6)模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)

二.圖算法:

(1)圖的深度優先遍歷和廣度優先遍歷.

(2)最短路徑算法(dijkstra,bellman-ford,floyd,heap+dijkstra)

(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)

(3)最小生成樹算法(prim,kruskal)

(poj1789,poj2485,poj1258,poj3026)

(4)拓撲排序 (poj1094)

(5)二分圖的最大匹配 (匈牙利算法) (poj3041,poj3020)

(6)最大流的增廣路算法(KM算法). (poj1459,poj3436)

三.數據結構.

(1)串 (poj1035,poj3080,poj1936)

(2)排序(快排、歸併排(與逆序數有關)、堆排) (poj2388,poj2299)

(3)簡單並查集的應用.

(4)哈希表和二分查找等高效查找法(數的Hash,串的Hash)

(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)

(5)哈夫曼樹(poj3253)

(6)堆

(7)trie樹(靜態建樹、動態建樹) (poj2513)

四.簡單搜索

(1)深度優先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)

(2)廣度優先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)

(3)簡單搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)

五.動態規劃

(1)揹包問題. (poj1837,poj1276)

(2)型以下表的簡單DP(可參考lrj的書 page149):

1.E[j]=opt{D[i]+w(i,j)} (poj3267,poj1836,poj1260,poj2533)

2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最長公共子序列)

(poj3176,poj1080,poj1159)

3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最優二分檢索樹問題)

六.數學

(1)組合數學:

1.加法原理和乘法原理.

2.排列組合.

3.遞推關係.

(POJ3252,poj1850,poj1019,poj1942)

(2)數論.

1.素數與整除問題

2.進制位.

3.同餘模運算.

(poj2635, poj3292,poj1845,poj2115)

(3)計算方法.

1.二分法求解單調函數相關知識.(poj3273,poj3258,poj1905,poj3122)

七.計算幾何學.

(1)幾何公式.

(2)叉積和點積的運用(如線段相交的斷定,點到線段的距離等). (poj2031,poj1039)

(3)多邊型的簡單算法(求面積)和相關斷定(點在多邊型內,多邊型是否相交)

(poj1408,poj1584)

(4)凸包. (poj2187,poj1113)

中級:

一.基本算法:

(1)C++的標準模版庫的應用. (poj3096,poj3007)

(2)較爲複雜的模擬題的訓練(poj3393,poj1472,poj3371,poj1027,poj2706)

二.圖算法:

(1)差分約束系統的創建和求解. (poj1201,poj2983)

(2)最小費用最大流(poj2516,poj2516,poj2195)

(3)雙連通份量(poj2942)

(4)強連通分支及其縮點.(poj2186)

(5)圖的割邊和割點(poj3352)

(6)最小割模型、網絡流規約(poj3308, )

三.數據結構.

(1)線段樹. (poj2528,poj2828,poj2777,poj2886,poj2750)

(2)靜態二叉檢索樹. (poj2482,poj2352)

(3)樹狀樹組(poj1195,poj3321)

(4)RMQ. (poj3264,poj3368)

(5)並查集的高級應用. (poj1703,2492)

(6)KMP算法. (poj1961,poj2406)

四.搜索

(1)最優化剪枝和可行性剪枝

(2)搜索的技巧和優化 (poj3411,poj1724)

(3)記憶化搜索(poj3373,poj1691)

 

五.動態規劃

(1)較爲複雜的動態規劃(如動態規劃解特別的施行商問題等)

(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)

(2)記錄狀態的動態規劃. (POJ3254,poj2411,poj1185)

(3)樹型動態規劃(poj2057,poj1947,poj2486,poj3140)

六.數學

(1)組合數學:

1.容斥原理.

2.抽屜原理.

3.置換羣與Polya定理(poj1286,poj2409,poj3270,poj1026).

4.遞推關係和母函數.

 

(2)數學.

1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)

2.機率問題. (poj3071,poj3440)

3.GCD、擴展的歐幾里德(中國剩餘定理) (poj3101)

(3)計算方法.

1.0/1分數規劃. (poj2976)

2.三分法求解單峯(單谷)的極值.

3.矩陣法(poj3150,poj3422,poj3070)

4.迭代逼近(poj3301)

(4)隨機化算法(poj3318,poj2454)

(5)雜題.

(poj1870,poj3296,poj3286,poj1095)

七.計算幾何學.

(1)座標離散化.

(2)掃描線算法(例如求矩形的面積和周長並,常和線段樹或堆一塊兒使用).

(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)

(3)多邊形的內核(半平面交)(poj3130,poj3335)

(4)幾何工具的綜合應用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)

高級:

一.基本算法要求:

(1)代碼快速寫成,精簡但不失風格

(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)

(2)保證正確性和高效性. poj3434

二.圖算法:

(1)度限制最小生成樹和第K最短路. (poj1639)

(2)最短路,最小生成樹,二分圖,最大流問題的相關理論(主要是模型創建和求解)

(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446

(3)最優比率生成樹. (poj2728)

(4)最小樹形圖(poj3164)

(5)次小生成樹.

(6)無向圖、有向圖的最小環

三.數據結構.

(1)trie圖的創建和應用. (poj2778)

(2)LCA和RMQ問題(LCA(最近公共祖先問題) 有離線算法(並查集+dfs) 和 在線算法

(RMQ+dfs)).(poj1330)

(3)雙端隊列和它的應用(維護一個單調的隊列,經常在動態規劃中起到優化狀態轉移的

目的). (poj2823)

(4)左偏樹(可合併堆).

(5)後綴樹(很是有用的數據結構,也是賽區考題的熱點).

(poj3415,poj3294)

四.搜索

(1)較麻煩的搜索題目訓練(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)

(2)廣搜的狀態優化:利用M進制數存儲狀態、轉化爲串用hash表判重、按位壓縮存儲狀態、雙向廣搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)

(3)深搜的優化:儘可能用位運算、必定要加剪枝、函數參數儘量少、層數不易過大、能夠考慮雙向搜索或者是輪換搜索、IDA*算法. (poj3131,poj2870,poj2286)

五.動態規劃

(1)須要用數據結構優化的動態規劃.

(poj2754,poj3378,poj3017)

(2)四邊形不等式理論.

(3)較難的狀態DP(poj3133)

六.數學

(1)組合數學.

1.MoBius反演(poj2888,poj2154)

2.偏序關係理論.

(2)博奕論.

1.極大極小過程(poj3317,poj1085)

2.Nim問題.

七.計算幾何學.

(1)半平面求交(poj3384,poj2540)

(2)可視圖的創建(poj2966)

(3)點集最小圓覆蓋.

(4)對踵點(poj2079)

八.綜合題.

(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263)

 

 

 

同時因爲我的練習的時候可能有些偏向性,可能上面的總結不是很全,還請你們提出和指正,並且因爲ACM的題目中專門針對某個算法的題目可能比較少出現,因此上面的分類中的題有可能有多種解法或者是一些算法的綜合,這都不會影響你們作題,但願練習的同窗可以認真,紮實地訓練,作到真正的理解算法,掌握算法.同時在論壇上還有許多前輩的分類,總結,你們也能夠按本身的狀況採用.注意FTP上有不少的資料,但願你們好好地利用.

 

 

若是同窗能在明年暑假前能掌握上面大部分算法,那你也基本上達到了訓練的目的,到暑假的時候你就能夠選擇本身比較喜歡的方面進行加深和強化,並且同窗們不要以爲看算法的證實是很麻煩的事,這能夠增強你的思惟能力,這在ACM中也很重要.同時也但願老隊員能幫助我整理習題和題目分類.同時ACM的題目是沒有範圍的,只能在平時中多積累多練習,多比別人多努力一點,你就會比別人多一線但願.

 

 

我補充些動態規劃、搜索方面的資料吧。

 

Dp狀態設計與方程總結

 

1.不徹底狀態記錄

<1>青蛙過河問題

<2>利用區間dp

2.揹包類問題

<1> 0-1揹包,經典問題

<2>無限揹包,經典問題

<3>斷定性揹包問題

<4>帶附屬關係的揹包問題

<5> + -1揹包問題

<6>雙揹包求最優值

<7>構造三角形問題

<8>帶上下界限制的揹包問題(012揹包)

3.線性的動態規劃問題

<1>積木遊戲問題

<2>決鬥(斷定性問題)

<3>圓的最大多邊形問題

<4>統計單詞個數問題

<5>棋盤分割

<6>日程安排問題

<7>最小逼近問題(求出兩數之比最接近某數/兩數之和等於某數等等)

<8>方塊消除遊戲(某區間能夠連續消去求最大效益)

<9>資源分配問題

<10>數字三角形問題

<11>漂亮的打印

<12>郵局問題與構造答案

<13>最高積木問題

<14>兩段連續和最大

<15>2次冪和問題

<16>N個數的最大M段子段和

<17>交叉最大數問題

4.斷定性問題的dp(如斷定整除、斷定可達性等)

<1>模K問題的dp

<2>特殊的模K問題,求最大(最小)模K的數

<3>變換數問題

5.單調性優化的動態規劃

<1>1-SUM問題

<2>2-SUM問題

<3>序列劃分問題(單調隊列優化)

6.剖分問題(多邊形剖分/石子合併/圓的剖分/乘積最大)

<1>凸多邊形的三角剖分問題

<2>乘積最大問題

<3>多邊形遊戲(多邊形邊上是操做符,頂點有權值)

<4>石子合併(N^3/N^2/NLogN各類優化)

7.貪心的動態規劃

<1>最優裝載問題

<2>部分揹包問題

<3>乘船問題

<4>貪心策略

<5>雙機調度問題Johnson算法

8.狀態dp

<1>牛仔射擊問題(博弈類)

<2>哈密頓路徑的狀態dp

<3>兩支點天平平衡問題

<4>一個有向圖的最接近二部圖

9.樹型dp

<1>完美服務器問題(每一個節點有3種狀態)

<2>小胖守皇宮問題

<3>網絡收費問題

<4>樹中漫遊問題

<5>樹上的博弈

<6>樹的最大獨立集問題

<7>樹的最大平衡值問題

<8>構造樹的最小環

 

 

 

先掌握搜索,動態規劃,貪心這些思想方法

而後學習各類技巧

 

ACM基本算法分類

 

 

 

ACM基本算法分類、推薦學習資料和配套pku習題一.動態規劃

 

參考資料:

 

劉汝佳《算法藝術與信息學競賽》《算法導論》

 

推薦題目:

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1141

 

簡單

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2288

 

中等,經典TSP問題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2411

 

中等,狀態壓縮DP

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1112

 

中等

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1848

 

中等,樹形DP。可參考《算法藝術與信息學競賽》動態規劃一節的樹狀模型

 

http://acm.zju.edu.cn/show_problem.php?pid=1234

 

中等,《算法藝術與信息學競賽》中的習題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1947

 

中等,《算法藝術與信息學競賽》中的習題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1946

 

中等,《算法藝術與信息學競賽》中的習題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1737

 

中等,遞推

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1821

 

中等,須要減小冗餘計算

 

http://acm.zju.edu.cn/show_problem.php?pid=2561

 

中等,四邊形不等式的簡單應用

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1038

 

較難,狀態壓縮DP,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1390

 

較難,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3017

 

較難,須要配合數據結構優化(個人題目^_^)

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1682

 

較難,寫起來比較麻煩

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2047

 

較難

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2152

 

難,樹形DP

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3028

 

難,狀態壓縮DP,題目頗有意思

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3124

 

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2915

 

很是難

 

 

 

二.搜索

 

參考資料:

 

劉汝佳《算法藝術與信息學競賽》

 

推薦題目:

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1011

 

簡單,深搜入門題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1324

 

中等,廣搜

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2044

 

中等,廣搜

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2286

 

較難,廣搜

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1945

 

難,IDA*,迭代加深搜索,須要較好的啓發函數

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2449

 

難,可重複K最短路,A*。可參考解題報告:

 

http://acm.pku.edu.cn/JudgeOnline/showcontest?contest_id=1144

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1190

 

難,深搜剪枝,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1084

 

難,《算法藝術與信息學競賽》習題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2989

 

難,深搜

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1167

 

較難,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1069

 

很難

 

 

三. 經常使用數據結構

 

參考資料:

 

劉汝佳《算法藝術與信息學競賽》

 

《算法導論》

 

線段樹資料:

 

http://home.ustc.edu.cn/~zhuhcheng/ACM/segment_tree.pdf

 

樹狀數組資料

 

http://home.ustc.edu.cn/~zhuhcheng/ACM/tree.ppt

 

關於線段樹和樹狀數組更多相關內容可在網上搜到

 

後綴數組資料

 

http://home.ustc.edu.cn/~zhuhcheng/ACM/suffix_array.pdf

 

http://home.ustc.edu.cn/~zhuhcheng/ACM/linear_suffix.pdf

 

推薦題目

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2482

 

較難,線段樹應用,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1151

 

簡單,線段樹應用矩形面積並,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3225

 

較難,線段樹應用,可參考解題報告

 

http://acm.pku.edu.cn/JudgeOnline/showcontest?contest_id=1233

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2155

 

難,二維樹狀數組。

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2777

 

中等,線段樹應用。

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2274

 

難,堆的應用,《算法藝術與信息學競賽》中有解答

 

http://acm.zju.edu.cn/show_problem.php?pid=2334

 

中等,左偏樹,二項式堆或其餘可合併堆的應用。

 

左偏樹參考 http://www.nist.gov/dads/HTML/leftisttree.html

 

二項式堆參見《算法導論》相關章節

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1182

 

中等,並查集

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1816

 

中等,字典樹

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2778

 

較難,多串匹配樹

 

參考: http://home.ustc.edu.cn/~zhuhcheng/ACM/zzy2004.pdf

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1743

 

難,後綴數組

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2774

 

較難,最長公共子串,經典問題,後綴數組

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2758

 

很難,後綴數組

 

可參考解題報告

 

http://acm.pku.edu.cn/JudgeOnline/showcontest?contest_id=1178

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2448

 

很難,數據結構綜合運用

 

四.圖論基礎

 

參考資料:

 

劉汝佳《算法藝術與信息學競賽》《算法導論》《網絡算法與複雜性理論》謝政

 

推薦題目:

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2337

 

簡單,歐拉路

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3177

 

中等,無向圖割邊

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2942

 

較難,無向圖雙連通分支

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1639

 

中等,最小度限制生成樹,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2728

 

中等,最小比率生成樹,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3013

 

簡單,最短路問題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1275

 

中等,差分約束系統,Bellman-Ford求解,《算法藝術與信息學競賽》中有解答

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1252

 

簡單,Bellman-Ford

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1459

 

中等,網絡流

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2391

 

較難,網絡流

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1325

 

中等,二部圖最大匹配

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2226

 

較難,二部圖最大匹配

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2195

 

中等,二部圖最大權匹配

 

KM算法參考《網絡算法與複雜性理論》

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2516

 

較難,二部圖最大權匹配

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1986

 

中等,LCA(最近公共祖先)問題

 

參考Tarjan's LCA algorithm 《算法導論》第21章習題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2723

 

較難,2-SAT問題

 

參考:http://home.ustc.edu.cn/~zhuhcheng/ACM/2-SAT.PPT

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2749

 

較難,2-SAT問題

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=3164

 

較難,最小樹形圖

 

參考《網絡算法與複雜性理論》中朱-劉算法

 

五.數論及組合計數基礎

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1811

 

簡單,素數斷定,大數分解

 

參考算法導論相關章節

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2888

 

較難,Burnside引理

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2891

 

中等,解模方程組

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2154

 

中等,經典問題,波利亞定理

 

http://cs.scu.edu.cn/soj/problem.action?id=2703

 

難,極好的題目,Burnside引理+模線性方程組

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2764

 

較難,須要數學方法,該方法在《具體數學》第七章有講

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1977

 

簡單,矩陣快速乘法

 

第01篇 ACM/ICPC競賽之基礎篇

1、ACM/ICPC競賽的特色

 

ACM/ICPC(國際大學生程序設計競賽)是以算法設計爲主的程序設計競賽,並不涉及具體的應用技術。

 

 

ACM/ICPC競賽以組隊形式參賽,每一個參賽隊由三名隊員組成,共同使用一臺計算機解題。一般每場比賽的試題爲6至10題,根據各隊的完成題數和罰時進行排名。題目提交經過稱爲完成,從比賽開始到提交成功所用的時間爲題目的基礎罰時,另外,一道題目每提交失敗一次,將增長20分鐘罰時。也就是說,參賽隊要儘量用最快的速度、最少的失敗次數,解決最多的題目。

 

2、輸入和輸出處理

試題通常採用標準輸入和輸出方式讀取輸入和產生輸出,在題目中會詳細描述輸入和輸出的格式和值域範圍,所寫的程序必定要嚴格遵照題目指定的輸入輸出格式。

 

在比賽試題的輸入和輸出處理上,針對一些常見的情形,有一些經常使用的方法。

 

一、多測試用例的輸入和輸出

 

有些試題在一次輸入中只包含一個測試用例,也就是說,程序每運行一次,只算一道題。也有些試題在一次輸入中包含多個測試用例,也就是說,程序每運行一次,要計算多道題。

 

 

對多用例輸入,一般會先輸入要計算的用例的個數,而後依次輸入每一個測試用例的輸入數據,但程序並不須要等到全部的測試用例都計算完後再輸出全部測試用例的計算結果,而是能夠讀入一個測試用例,輸出一個結果,再讀入一個測試用例,再輸出一個結果。所以對多用例輸入的試題,能夠用這樣的輸入模式:

 

以C++爲例:

 

int n;

 

cin >> n;

 

for (int i=0; i<n; i++)

 

{

 

讀入測試用例數據

 

計算

 

輸出計算結果

 

}

 

二、單測試用例輸入的結束判斷

對單用例輸入,最主要的問題是如何知道輸入何時結束。

 

有些試題會指定某種特殊的輸入值做爲輸入的結束標誌,這種狀況比較容易處理,只須在讀入後,判斷一下讀入的內容是否爲約定結束值便可。

 

有些試題並不指定特殊的輸入值,而是以EOF(文件結束標誌)做爲結束標誌。若是從文件流讀入,當讀到文件尾時,輸入返回EOF。若是從鍵盤讀入時,在Windows的終端中,是以Ctrl+Z表示EOF。對於這種狀況,能夠用這樣的輸入模式:

 

以C++爲例:

 

int m, n; // 假設要連續輸入一組整數對

 

while (cin>>m>>n)

 

{

 

處理整數對(m, n)

 

}

 

以C語言爲例:

 

int m, n;

 

while (scanf("%d%d", &m, &n)==2)

 

{

 

處理整數對(m, n)

 

}

 

3、數據結構的設計

不少試題中已經給出了數據量的上限,所以能夠很方便地以數組的方式定義數據結構。但也要注意到有些題目中沒有明確指出數據上限時,切不可盲目定義數組大小。

 

 

例如在題1070(多項式求和)中,並未說明輸入多項式的項數,對這種狀況就不宜用數組方式來表示多項式了——除非你的運氣足夠好,所開闢的數組大小可以經受全部的測試用例的考驗。

 

除了使用通常的數組或鏈表結構外,對使用C++的選手來講,STL也是一大利器,充分運用能夠有效提升編程的效率和正確性。

 

4、測試用例的考慮

在試題中一般會給出測試用例的樣例,這一般會被咱們用來測試本身的程序,並且不少選手每每在正確計算出測試用例樣例時,會認爲本身的程序是正確的。

 

 

其實測試用例的樣例只是測試用例的個例,實際用於測試的測試用例每每會涵蓋各類極限狀況和邊界狀況,並且有時測試用例的數量還會比較大,甚至會重複測試同一個測試用例。所以咱們的程序可以經過樣例測試,未必可以經過全部的測試用例的測試,一方面要全面考慮全部可能的極限狀況和邊界狀況,一方面程序要有足夠的效率。

 

 

 

2008-7-17 01:29 回覆

 

 

狂暈的迷戰士

14位粉絲

2樓

第03篇 ACM/ICPC競賽之STL--pair

STL的<utility>頭文件中描述了一個看上去很是簡單的模板類pair,用來表示一個二元組或元素對,並提供了按照字典序對元素對進行大小比較的比較運算符模板函數。

 

例如,想要定義一個對象表示一個平面座標點,則能夠:

 

pair<double, double> p1;

cin >> p1.first >> p1.second;

 

 

pair模板類須要兩個參數:首元素的數據類型和尾元素的數據類型。pair模板類對象有兩個成員:first和second,分別表示首元素和尾元素。

 

在<utility>中已經定義了pair上的六個比較運算符:<、>、<=、>=、==、!=,其規則是先比較first,first相等時再比較second,這符合大多數應用的邏輯。

固然,也能夠經過重載這幾個運算符來從新指定本身的比較邏輯。

 

除了直接定義一個pair對象外,若是須要即時生成一個pair對象,也能夠調用在<utility>中定義的一個模板函數:make_pair。make_pair須要兩個參數,

分別爲元素對的首元素和尾元素。

 

在題1067--Ugly Numbers中,就能夠用pair來表示推演樹上的結點,用first表示結點的值,用second表示結點是由父結點乘以哪個因子獲得的。

 

#include <iostream>

#include <queue>

using namespace std;

typedef pair<unsigned long, int> node_type;

main()

{ unsigned long result[1500];

priority_queue< node_type, vector<node_type>, greater<node_type> > Q;

Q.push( make_pair(1, 2) );

for (int i=0; i<1500; i++)

{

node_type node = Q.top();

Q.pop();

switch(node.second)

{ case 2: Q.push( make_pair(node.first*2, 2) );

case 3: Q.push( make_pair(node.first*3, 3) );

case 5: Q.push( make_pair(node.first*5, 5) );

}

result[i] = node.first;

}

int n; cin >> n;

while (n>0)

{

cout << result[n-1] << endl;

cin >> n;

}

return 1;

}

<utility>看上去是很簡單的一個頭文件,可是<utility>的設計中卻濃縮反映了STL設計的基本思想。有意深刻了解和研究STL的同窗,仔細閱讀和體會這個簡單的頭文件,

不失爲一種入門的途徑。

2008-7-17 01:31 回覆

 

 

狂暈的迷戰士

14位粉絲

3樓

第04篇 ACM/ICPC競賽之STL--vector

在STL的<vector>頭文件中定義了vector(向量容器模板類),vector容器以連續數組的方式存儲元素序列,能夠將vector看做是以順序結構實現的線性表。

當咱們在程序中須要使用動態數組時,vector將會是理想的選擇,vector能夠在使用過程當中動態地增加存儲空間。

 

vector模板類須要兩個模板參數,第一個參數是存儲元素的數據類型,第二個參數是存儲分配器的類型,其中第二個參數是可選的,若是不給出第二個參數,

將使用默認的分配器。

 

下面給出幾個經常使用的定義vector向量對象的方法示例:

 

vector<int> s;

定義一個空的vector對象,存儲的是int類型的元素。

 

vector<int> s(n);

定義一個含有n個int元素的vector對象。

 

vector<int> s(first, last);

定義一個vector對象,並從由迭代器first和last定義的序列[first, last)中複製初值。

 

vector的基本操做有:

 

s[i]

直接如下標方式訪問容器中的元素。

 

s.front()

返回首元素。

 

s.back()

返回尾元素。

 

s.push_back(x)

向表尾插入元素x。

 

s.size()

返回表長。

 

s.empty()

當表空時,返回真,不然返回假。

 

s.pop_back()

刪除表尾元素。

 

s.begin()

返回指向首元素的隨機存取迭代器。

 

s.end()

返回指向尾元素的下一個位置的隨機存取迭代器。

 

s.insert(it, x)

向迭代器it指向的元素前插入新元素val。

 

s.insert(it, n, x)

向迭代器it指向的元素前插入n個x。

 

s.insert(it, first, last)

將由迭代器first和last所指定的序列[first, last)插入到迭代器it指向的元素前面。

 

s.erase(it)

刪除由迭代器it所指向的元素。

 

s.erase(first, last)

刪除由迭代器first和last所指定的序列[first, last)。

 

s.reserve(n)

預分配緩衝空間,使存儲空間至少可容納n個元素。

 

s.resize(n)

改變序列的長度,超出的元素將會被刪除,若是序列須要擴展(原空間小於n),元素默認值將填滿擴展出的空間。

 

s.resize(n, val)

改變序列的長度,超出的元素將會被刪除,若是序列須要擴展(原空間小於n),將用val填滿擴展出的空間。

 

s.clear()

刪除容器中的全部的元素。

 

s.swap(v)

將s與另外一個vector對象v進行交換。

 

s.assign(first, last)

將序列替換成由迭代器first和last所指定的序列[first, last)。[first, last)不能是原序列中的一部分。

 

要注意的是,resize操做和clear操做都是對錶的有效元素進行的操做,但並不必定會改變緩衝空間的大小。

 

另外,vector還有其餘一些操做如反轉、取反等,再也不一下列舉。

 

vector上還定義了序列之間的比較操做運算符(>, <, >=, <=, ==, !=),能夠按照字典序比較兩個序列。

 

仍是來看一些示例代碼。輸入個數不定的一組整數,再將這組整數按倒序輸出,以下所示:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> L;

int x;

while (cin>>x) L.push_back(x);

for (int i=L.size()-1; i>=0; i--) cout << L[i] << " ";

cout << endl;

return 1;

}

2008-7-17 01:31 回覆

 

 

狂暈的迷戰士

14位粉絲

4樓

第04篇 ACM/ICPC競賽之STL--vector

在STL的<vector>頭文件中定義了vector(向量容器模板類),vector容器以連續數組的方式存儲元素序列,能夠將vector看做是以順序結構實現的線性表。

當咱們在程序中須要使用動態數組時,vector將會是理想的選擇,vector能夠在使用過程當中動態地增加存儲空間。

 

vector模板類須要兩個模板參數,第一個參數是存儲元素的數據類型,第二個參數是存儲分配器的類型,其中第二個參數是可選的,若是不給出第二個參數,

將使用默認的分配器。

 

下面給出幾個經常使用的定義vector向量對象的方法示例:

 

vector<int> s;

定義一個空的vector對象,存儲的是int類型的元素。

 

vector<int> s(n);

定義一個含有n個int元素的vector對象。

 

vector<int> s(first, last);

定義一個vector對象,並從由迭代器first和last定義的序列[first, last)中複製初值。

 

vector的基本操做有:

 

s[i]

直接如下標方式訪問容器中的元素。

 

s.front()

返回首元素。

 

s.back()

返回尾元素。

 

s.push_back(x)

向表尾插入元素x。

 

s.size()

返回表長。

 

s.empty()

當表空時,返回真,不然返回假。

 

s.pop_back()

刪除表尾元素。

 

s.begin()

返回指向首元素的隨機存取迭代器。

 

s.end()

返回指向尾元素的下一個位置的隨機存取迭代器。

 

s.insert(it, x)

向迭代器it指向的元素前插入新元素val。

 

s.insert(it, n, x)

向迭代器it指向的元素前插入n個x。

 

s.insert(it, first, last)

將由迭代器first和last所指定的序列[first, last)插入到迭代器it指向的元素前面。

 

s.erase(it)

刪除由迭代器it所指向的元素。

 

s.erase(first, last)

刪除由迭代器first和last所指定的序列[first, last)。

 

s.reserve(n)

預分配緩衝空間,使存儲空間至少可容納n個元素。

 

s.resize(n)

改變序列的長度,超出的元素將會被刪除,若是序列須要擴展(原空間小於n),元素默認值將填滿擴展出的空間。

 

s.resize(n, val)

改變序列的長度,超出的元素將會被刪除,若是序列須要擴展(原空間小於n),將用val填滿擴展出的空間。

 

s.clear()

刪除容器中的全部的元素。

 

s.swap(v)

將s與另外一個vector對象v進行交換。

 

s.assign(first, last)

將序列替換成由迭代器first和last所指定的序列[first, last)。[first, last)不能是原序列中的一部分。

 

要注意的是,resize操做和clear操做都是對錶的有效元素進行的操做,但並不必定會改變緩衝空間的大小。

 

另外,vector還有其餘一些操做如反轉、取反等,再也不一下列舉。

 

vector上還定義了序列之間的比較操做運算符(>, <, >=, <=, ==, !=),能夠按照字典序比較兩個序列。

 

仍是來看一些示例代碼。輸入個數不定的一組整數,再將這組整數按倒序輸出,以下所示:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> L;

int x;

while (cin>>x) L.push_back(x);

for (int i=L.size()-1; i>=0; i--) cout << L[i] << " ";

cout << endl;

return 1;

}

2008-7-17 01:32 回覆

 

 

狂暈的迷戰士

14位粉絲

5樓

第05篇 ACM/ICPC競賽之STL--iterator簡介

iterator(迭代器)是用於訪問容器中元素的指示器,從這個意義上說,iterator(迭代器)至關於數據結構中所說的"遍歷指針",也能夠把iterator(迭代器)看做是一種泛化的指針。

 

STL中關於iterator(迭代器)的實現是至關複雜的,這裏咱們暫時不去詳細討論關於iterator(迭代器)的實現和使用,而只對iterator(迭代器)作一點簡單的介紹。

 

簡單地說,STL中有如下幾類iterator(迭代器):

 

輸入iterator(迭代器),在容器的連續區間內向前移動,能夠讀取容器內任意值;

輸出iterator(迭代器),把值寫進它所指向的容器中;

前向iterator(迭代器),讀取隊列中的值,並能夠向前移動到下一位置(++p,p++);

雙向iterator(迭代器),讀取隊列中的值,並能夠向前向後遍歷容器;

隨機訪問iterator(迭代器), 能夠直接如下標方式對容器進行訪問,vector的iterator(迭代器)就是這種iterator(迭代器);

流iterator(迭代器),能夠直接輸出、輸入流中的值;

每種STL容器都有本身的iterator(迭代器)子類,下面先來看一段簡單的示例代碼:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> s;

for (int i=0; i<10; i++) s.push_back(i);

for (vector<int>::iterator it=s.begin(); it!=s.end(); it++)

cout << *it << " ";

cout << endl;

return 1;

}

 

vector的begin()和end()方法都會返回一個vector::iterator對象,分別指向vector的首元素位置和尾元素的下一個位置(咱們能夠稱之爲結束標誌位置)。

 

對一個iterator(迭代器)對象的使用與一個指針變量的使用極爲類似,或者能夠這樣說,指針就是一個很是標準的iterator(迭代器)。

 

再來看一段稍微特別一點的代碼:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> s;

s.push_back(1);

s.push_back(2);

s.push_back(3);

copy(s.begin(), s.end(), ostream_iterator<int>(cout, " "));

cout <<endl;

return 1;

}

 

這段代碼中的copy就是STL中定義的一個模板函數,copy(s.begin(), s.end(), ostream_iterator<int>(cout, " "));的意思是將由s.begin()至s.end()(不含s.end())所指定的序列複製到標準輸出流cout中,用" "做爲每一個元素的間隔。也就是說,這句話的做用其實就是將表中的全部內容依次輸出。

 

iterator(迭代器)是STL容器和算法之間的"膠合劑",幾乎全部的STL算法都是經過容器的iterator(迭代器)來訪問容器內容的。只有經過有效地運用iterator(迭代器),纔可以有效地運用STL強大的算法功能。

2008-7-17 01:32 回覆

 

 

狂暈的迷戰士

14位粉絲

6樓

第05篇 ACM/ICPC競賽之STL--iterator簡介

iterator(迭代器)是用於訪問容器中元素的指示器,從這個意義上說,iterator(迭代器)至關於數據結構中所說的"遍歷指針",也能夠把iterator(迭代器)看做是一種泛化的指針。

 

STL中關於iterator(迭代器)的實現是至關複雜的,這裏咱們暫時不去詳細討論關於iterator(迭代器)的實現和使用,而只對iterator(迭代器)作一點簡單的介紹。

 

簡單地說,STL中有如下幾類iterator(迭代器):

 

輸入iterator(迭代器),在容器的連續區間內向前移動,能夠讀取容器內任意值;

輸出iterator(迭代器),把值寫進它所指向的容器中;

前向iterator(迭代器),讀取隊列中的值,並能夠向前移動到下一位置(++p,p++);

雙向iterator(迭代器),讀取隊列中的值,並能夠向前向後遍歷容器;

隨機訪問iterator(迭代器), 能夠直接如下標方式對容器進行訪問,vector的iterator(迭代器)就是這種iterator(迭代器);

流iterator(迭代器),能夠直接輸出、輸入流中的值;

每種STL容器都有本身的iterator(迭代器)子類,下面先來看一段簡單的示例代碼:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> s;

for (int i=0; i<10; i++) s.push_back(i);

for (vector<int>::iterator it=s.begin(); it!=s.end(); it++)

cout << *it << " ";

cout << endl;

return 1;

}

 

vector的begin()和end()方法都會返回一個vector::iterator對象,分別指向vector的首元素位置和尾元素的下一個位置(咱們能夠稱之爲結束標誌位置)。

 

對一個iterator(迭代器)對象的使用與一個指針變量的使用極爲類似,或者能夠這樣說,指針就是一個很是標準的iterator(迭代器)。

 

再來看一段稍微特別一點的代碼:

 

#include <iostream>

#include <vector>

using namespace std;

main()

{

vector<int> s;

s.push_back(1);

s.push_back(2);

s.push_back(3);

copy(s.begin(), s.end(), ostream_iterator<int>(cout, " "));

cout <<endl;

return 1;

}

 

這段代碼中的copy就是STL中定義的一個模板函數,copy(s.begin(), s.end(), ostream_iterator<int>(cout, " "));的意思是將由s.begin()至s.end()(不含s.end())所指定的序列複製到標準輸出流cout中,用" "做爲每一個元素的間隔。也就是說,這句話的做用其實就是將表中的全部內容依次輸出。

 

iterator(迭代器)是STL容器和算法之間的"膠合劑",幾乎全部的STL算法都是經過容器的iterator(迭代器)來訪問容器內容的。只有經過有效地運用iterator(迭代器),纔可以有效地運用STL強大的算法功能。

2008-7-17 01:33 回覆

 

 

狂暈的迷戰士

14位粉絲

7樓

第06篇 ACM/ICPC競賽之STL--string

字符串是程序中常常要表達和處理的數據,咱們一般是採用字符數組或字符指針來表示字符串。STL爲咱們提供了另外一種使用起來更爲便捷的字符串的表達方式:string。string類的定義在頭文件<string>中。

 

string類其實能夠看做是一個字符的vector,vector上的各類操做均可以適用於string,另外,string類對象還支持字符串的拼合、轉換等操做。

 

下面先來看一個簡單的例子:

 

#include <iostream>

#include <string>

using namespace std;

main()

{

string s = "Hello! ", name;

cin >> name;

s += name;

s += '!';

cout << s << endl;

return 1;

}

 

 

再以題1064--Parencoding爲例,看一段用string做爲容器,實現由P代碼還原括號字符串的示例代碼片斷:

 

int m;

cin >> m; // P編碼的長度

string str; // 用來存放還原出來的括號字符串

int leftpa = 0; // 記錄已出現的左括號的總數

for (int j=0; j<m; j++)

{

int p;

cin >> p;

for (int k=0; k<p-leftpa; k++) str += '(';

str += ')';

leftpa = p;

}

2008-7-17 01:33 回覆

 

 

狂暈的迷戰士

14位粉絲

9樓

 

看下面這個簡單的示例:

 

#include <iostream>

#include <queue>

using namespace std;

class T

{

public:

int x, y, z;

T(int a, int b, int c):x(a), y(b), z?

{

}

};

bool operator < (const T &t1, const T &t2)

{

return t1.z < t2.z; // 按照z的順序來決定t1和t2的順序

}

main()

{

priority_queue<T> q;

q.push(T(4,4,3));

q.push(T(2,2,5));

q.push(T(1,5,4));

q.push(T(3,3,6));

 

while (!q.empty())

{

T t = q.top(); q.pop();

cout << t.x << " " << t.y << " " << t.z << endl;

}

return 1;

}

 

輸出結果爲(注意是按照z的順序從大到小出隊的):

 

3 3 6

2 2 5

1 5 4

4 4 3

 

再看一個按照z的順序從小到大出隊的例子:

 

#include <iostream>

#include <queue>

using namespace std;

class T

{

public:

int x, y, z;

T(int a, int b, int c):x(a), y(b), z?

{

}

};

bool operator > (const T &t1, const T &t2)

{

return t1.z > t2.z;

}

main()

{

priority_queue<T, vector<T>, greater<T> > q;

q.push(T(4,4,3));

q.push(T(2,2,5));

q.push(T(1,5,4));

q.push(T(3,3,6));

 

while (!q.empty())

{

T t = q.top(); q.pop();

cout << t.x << " " << t.y << " " << t.z << endl;

}

return 1;

}

 

輸出結果爲:

 

4 4 3

1 5 4

2 2 5

3 3 6

 

若是咱們把第一個例子中的比較運算符重載爲:

 

bool operator < (const T &t1, const T &t2)

{

return t1.z > t2.z; // 按照z的順序來決定t1和t2的順序

}

 

則第一個例子的程序會獲得和第二個例子的程序相同的輸出結果。

 

再回顧一下用優先隊列實現的題1067--Ugly Numbers的代碼:

 

#include <iostream>

#include <queue>

using namespace std;

typedef pair<unsigned long int, int> node_type;

main( int argc, char *argv[] )

{

unsigned long int result[1500];

priority_queue< node_type, vector<node_type>, greater<node_type> > Q;

Q.push( make_pair(1, 3) );

for (int i=0; i<1500; i++)

{

node_type node = Q.top();

Q.pop();

switch(node.second)

{

case 3: Q.push( make_pair(node.first*2, 3) );

case 2: Q.push( make_pair(node.first*3, 2) );

case 1: Q.push( make_pair(node.first*5, 1) );

}

result[i] = node.first;

}

int n;

cin >> n;

while (n>0)

{

cout << result[n-1] << endl;

cin >> n;

}

return 1;

}

2008-7-17 01:34 回覆

 

 

狂暈的迷戰士

14位粉絲

10樓

第09篇 ACM/ICPC競賽之STL--algorithm

<algorithm>無疑是STL中最大的一個頭文件,它是由一大堆模板函數組成的。

 

下面列舉出<algorithm>中的模板函數:

 

adjacent_find / binary_search / copy / copy_backward / count / count_if / equal / equal_range / fill / fill_n / find / find_end / find_first_of / find_if / for_each / generate / generate_n / includes / inplace_merge / iter_swap / lexicographical_compare / lower_bound / make_heap / max / max_element / merge / min / min_element / mismatch / next_permutation / nth_element / partial_sort / partial_sort_copy / partition / pop_heap / prev_permutation / push_heap / random_shuffle / remove / remove_copy / remove_copy_if / remove_if / replace / replace_copy / replace_copy_if / replace_if / reverse / reverse_copy / rotate / rotate_copy / search / search_n / set_difference / set_intersection / set_symmetric_difference / set_union / sort / sort_heap / stable_partition / stable_sort / swap / swap_ranges / transform / unique / unique_copy / upper_bound

 

若是詳細敘述每個模板函數的使用,足夠寫一本書的了。仍是來看幾個簡單的示例程序吧。

 

示例程序之一,for_each遍歷容器:

 

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

 

int Visit(int v) // 遍歷算子函數

{

cout << v << " ";

return 1;

}

 

class MultInt // 定義遍歷算子類

{

private:

int factor;

public:

MultInt(int f) : factor(f)

{

}

void operator()(int &elem) const

{

elem *= factor;

}

};

 

main()

{

vector<int> L;

for (int i=0; i<10; i++) L.push_back(i);

for_each(L.begin(), L.end(), Visit);

cout << endl;

for_each(L.begin(), L.end(), MultInt(2));

for_each(L.begin(), L.end(), Visit);

cout << endl;

return 1;

}

 

程序的輸出結果爲:

 

0 1 2 3 4 5 6 7 8 9

0 2 4 6 8 10 12 14 16 18

 

示例程序之二,min_element/max_element,找出容器中的最小/最大值:

 

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

 

main()

{

vector<int> L;

for (int i=0; i<10; i++) L.push_back(i);

vector<int>::iterator min_it = min_element(L.begin(), L.end());

vector<int>::iterator max_it = max_element(L.begin(), L.end());

cout << "Min is " << *min_it << endl;

cout << "Max is " << *max_it << endl;

return 1;

}

 

程序的輸出結果爲:

 

Min is 0

Max is 9

 

示例程序之三,sort對容器進行排序:

 

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

void Print(vector<int> &L)

{

for (vector<int>::iterator it=L.begin(); it!=L.end(); it++)

cout << *it << " ";

cout << endl;

}

main()

{

vector<int> L;

for (int i=0; i<5; i++) L.push_back(i);

for (int i=9; i>=5; i--) L.push_back(i);

Print(L);

sort(L.begin(), L.end());

Print(L);

sort(L.begin(), L.end(), greater<int>()); // 按降序排序

Print(L);

return 1;

}

 

程序的輸出結果爲:

 

0 1 2 3 4 9 8 7 6 5

0 1 2 3 4 5 6 7 8 9

9 8 7 6 5 4 3 2 1 0

 

示例程序之四,copy在容器間複製元素:

 

#include <vector>

#include <algorithm>

#include <iostream>

using namespace std;

main( )

{

// 先初始化兩個向量v1和v2

vector <int> v1, v2;

for (int i=0; i<=5; i++) v1.push_back(10*i);

for (int i=0; i<=10; i++) v2.push_back(3*i);

 

cout << "v1 = ( " ;

for (vector <int>::iterator it=v1.begin(); it!=v1.end(); it++)

cout << *it << " ";

cout << ")" << endl;

 

cout << "v2 = ( " ;

for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)

cout << *it << " ";

cout << ")" << endl;

 

// 將v1的前三個元素複製到v2的中間

copy(v1.begin(), v1.begin()+3, v2.begin()+4);

 

cout << "v2 with v1 insert = ( " ;

for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)

cout << *it << " ";

cout << ")" << endl;

 

// 在v2內部進行復制,注意參數2表示結束位置,結束位置不參與複製

copy(v2.begin()+4, v2.begin()+7, v2.begin()+2);

 

cout << "v2 with shifted insert = ( " ;

for (vector <int>::iterator it=v2.begin(); it!=v2.end(); it++)

cout << *it << " ";

cout << ")" << endl;

return 1;

}

 

程序的輸出結果爲:

 

v1 = ( 0 10 20 30 40 50 )

v2 = ( 0 3 6 9 12 15 18 21 24 27 30 )

v2 with v1 insert = ( 0 3 6 9 0 10 20 21 24 27 30 )

v2 with shifted insert = ( 0 3 0 10 20 10 20 21 24 27 30 )

2008-7-17 01:37 回覆

 

 

狂暈的迷戰士

14位粉絲

11樓

第10篇 ACM/ICPC競賽之算法策略

ACM/ICPC競賽其實就是算法設計和編碼的競賽,熟悉各類經常使用算法和算法設計策略並能靈活運用是很是必要的。

 

這裏對幾種在競賽中常常用到的算法設計策略作一簡單的介紹。

 

一、窮舉法

窮舉法是最基本的算法設計策略,其思想是列舉出問題全部的可能解,逐一進行判別,找出知足條件的解。

 

窮舉法的運用關鍵在於解決兩個問題:

 

如何列舉全部的可能解;

 

如何判別可能解是否知足條件;

 

在運用窮舉法時,容易出現的問題是可能解過多,致使算法效率很低,這就須要對列舉可能解的方法進行優化。

 

以題1041--純素數問題爲例,從1000到9999均可以看做是可能解,能夠經過對全部這些可能解逐一進行判別,找出其中的純素數,但只要稍做分析,就會發現其實能夠大幅度地下降可能解的範圍。根據題意易知,個位只多是三、五、7,再根據題意可知,能夠在三、五、7的基礎上,先找出全部的二位純素數,再在二位純素數基礎上找出三位純素數,最後在三位純素數的基礎上找出全部的四位純素數。

 

二、分治法

分治法也是應用很是普遍的一種算法設計策略,其思想是將問題分解爲若干子問題,從而能夠遞歸地求解各子問題,再綜合出問題的解。

 

分治法的運用關鍵在於解決三個問題:

 

肯定分治規則,即如何分解問題。

 

肯定終結條件,即問題分解到什麼狀態時能夠直接求解。

 

肯定概括方法,即如何由子問題的解獲得原問題的解。這一步並不老是須要的,由於對某些問題來講,並不須要對子問題的解進行復雜的概括。

 

咱們熟知的如漢諾塔問題、折半查找算法、快速排序算法等都是分治法運用的典型案例。

 

以題1045--Square Coins爲例,先對題意進行分析,可設一個函數f(m, n)等於用面值不超過n2的貨幣構成總值爲m的方案數,則容易推導出:

 

f(m, n) = f(m-0*n*n, n-1)+f(m-1*n*n, n-1)+f(m-2*n*n, n-1)+...+f(m-k*n*n, n-1)

這裏的k是幣值爲n2的貨幣最多能夠用多少枚,即k=m/(n*n)。

 

也很容易分析出,f(m, 1) = f(1, n) = 1

 

對於這樣的題目,一旦分析出了遞推公式,程序就很是好寫了。因此在動手開始寫程序以前,分析工做作得越完全,邏輯描述越準確、簡潔,寫起程序來就會越容易。

 

三、動態規劃法

動態規劃法多用來計算最優問題,動態規劃法與分治法的基本思想是一致的,但處理的手法不一樣。動態規劃法在運用時,要先對問題的分治規律進行分析,找出終結子問題,以及子問題向父問題概括的規則,而算法則直接從終結子問題開始求解,逐層向上概括,直到概括出原問題的解。

 

動態規劃法多用於在分治過程當中,子問題可能重複出現的狀況,在這種狀況下,若是按照常規的分治法,自上向下分治求解,則重複出現的子問題就會被重複地求解,從而增大了冗餘計算量,下降了求解效率。而採用動態規劃法,自底向上求解,每一個子問題只計算一次,就能夠避免這種重複的求解了。

 

動態規劃法還有另一種實現形式,即備忘錄法。備忘錄的基本思想是設立一個稱爲備忘錄的容器,記錄已經求得解的子問題及其解。仍然採用與分治法相同的自上向下分治求解的策略,只是對每個分解出的子問題,先在備忘錄中查找該子問題,若是備忘錄中已經存在該子問題,則不須再求解,能夠從備忘錄中直接獲得解,不然,對子問題遞歸求解,且每求得一個子問題的解,都將子問題及解存入備忘錄中。

 

例如,在題1045--Square Coins中,能夠採用分治法求解,也能夠採用動態規劃法求解,即從f(m, 1)和f(1, n)出發,逐層向上計算,直到求得f(m, n)。

 

在競賽中,動態規劃和備忘錄的思想還能夠有另外一種用法。有些題目中的可能問題數是有限的,而在一次運行中可能須要計算多個測試用例,能夠採用備忘錄的方法,預先將全部的問題的解記錄下來,而後輸入一個測試用例,就查備忘錄,直接找到答案輸出。這在各問題之間存在父子關係的狀況下,會更有效。例如,在題1045--Square Coins中,題目中已經指出了最大的目標幣值不超過300,也就是說問題數只有300個,並且各問題的計算中存在重疊的子問題,能夠採用動態規劃法,將全部問題的解先所有計算出來,再依次輸入測試用例數據,並直接輸出答案。

 

四、回溯法

回溯法是基於問題狀態樹搜索的求解法,其可適用範圍很廣。從某種角度上說,能夠把回溯法看做是優化了的窮舉法。回溯法的基本思想是逐步構造問題的可能解,一邊構造,一邊用約束條件進行判別,一旦發現已經不可能構造出知足條件的解了,則退回上一步構造過程,從新進行構造。這個退回的過程,就稱之爲"回溯"。

 

回溯法在運用時,要解決的關鍵問題在於:

 

如何描述局部解。

 

如何擴展局部解和回溯局部解。

 

如何判別局部解。

 

回溯法的經典案例也不少,例如全排列問題、N後問題等。

 

五、貪心法

貪心法也是求解最優問題的經常使用算法策略,利用貪心法策略所設計的算法,一般效率較高,算法簡單。貪心法的基本思想是對問題作出目前看來最好的選擇,即貪心選擇,並使問題轉化爲規模更小的子問題。如此迭代,直到子問題能夠直接求解。

 

基於貪心法的經典算法例如:哈夫曼算法、最小生成樹算法、最短路徑算法等。

 

可是,貪心法的運用是有條件的,必須可以證實貪心選擇可以導出最優解,且轉化出的子問題與原問題是同性質的問題,才能使用貪心法求解。

 

一個比較經典的貪心法求解的問題就是找硬幣問題:有一、二、五、十、20、50、100七種面值的硬幣,要支付指定的金額,問怎麼支付所用的硬幣個數最少。這是一個很是平常化的問題,憑直覺咱們會想到,儘量先用大面值的硬幣,這就是"貪心選擇",而在這個問題上,這個貪心選擇也是正確的。

 

六、限界剪枝法

限界剪枝法是求解較複雜最優問題的一種算法策略,與回溯法相似的是,限界剪枝法也是在問題狀態空間樹上進行搜索,但回溯法是搜索通常解,而限界剪枝法則是搜索最優解。限界剪枝法的基本思想是經過找出權值函數的上下界函數,如下界函數來指導搜索的方向,以上界函數來幫助剪除一些不可能含有最優解的分枝。

 

關於算法和算法策略的討論是一個很是龐大的話題,幾乎每一個問題點都能擴展出一大堆可討論的內容和案例。我實在不知道該怎樣用簡短的幾篇文字就可以把這個話題說透,這裏只能走馬觀花地對競賽中常常用到的幾種策略作一極爲簡略的介紹。

 

也許咱們能夠在之後的文章中,針對具體的題目進行算法和策略的分析,效果可能會更好。

2008-7-17 01:37 回覆

 

 

狂暈的迷戰士

14位粉絲

12樓

第11篇 ACM/ICPC競賽之調試

在寫程序時,調試程序也是一個重要的環節。怎樣纔可以更有效地調試程序,發現並修正錯誤呢?

 

一、調試中的輸入輸出

爲了調試程序,咱們可能須要反覆執行程序,也就須要反覆輸入相同或不相同的測試數據。若是每次調試運行時都是以手工的方式輸入測試數據,相信不少人都會以爲不勝其煩。其實咱們能夠用一些輔助的手段來簡化這個過程。

 

方法一:使用剪貼板

 

能夠將輸入數據預先寫好(用記事本、開發環境的編輯器或隨便什麼可以錄入的東西

相關文章
相關標籤/搜索