BFS
- 求最小
- 基迭代,不會爆棧
Flood fill算法:
可以在線性時間復雜度內,找到某個點所在的連通塊。
//Home鍵到行首,End鍵到行尾
AcWing 1097. 池塘計數
AcWing 1098. 城堡問題
AcWing 1106. 山峰和山谷
最短路模型:
所有邊權相等時,可以在線性時間內得到單源或多源最短路(可視為特殊的dijkstra)
AcWing 1076. 迷宮問題
AcWing 188. 武士風度的牛
AcWing 1100. 抓住那頭牛
AcWing 173. 矩陣距離
- 保證任意時刻搜索隊列中的值都具有
- 兩段性 //最多有兩段,但不一定是兩段
- 單調性
最小步數模型:
用哈希(unoreded_map)或康托展開
AcWing 1107. 魔板
雙端隊列廣搜:
用deque(front、push_front、pop_front、push_back)
AcWing 175. 電路維修
每個節點可能被更新(入隊)多次。當終點第一次被擴展(出隊)時,就能得到從起點到終點的最短距離。
//奇點:橫縱坐標之和是奇數的點
偶點:橫縱坐標之和是偶數的點
//‘\’是轉義字符,因此需要打兩個;
字符數組最后還有‘\n’,不要忘記
e.g. char cs[5]=“\\/\\/”;
雙向廣搜:
極大地縮小搜索的空間范圍,提高搜索的效率。
狀態空間數量一般為指數級。
適用於「最小步數模型」,但一般不用於數據較小的「flood fill算法」或「最短路模型」。
優化:每次選擇當前元素數量較小的隊列進行擴展
AcWing 190. 字串變換
//返回字符串t的一個子串:
i:起始下標
a[j].size():子串長度(若超過字符串t的長度則輸出到結尾,若不寫也直接輸出到結尾)
翻轉一個vector:。翻轉一個數組,元素存放在下標1~n:
。
A*:
當題目一定有解時才用,無解時效率低於普通BFS。
邊權任意,但不能有負權回路。
將BFS中的隊列換成優先隊列(小根堆)。隊列中存儲從起點到當前點的真實距離與從當前點到終點的估計距離之和。
Dijkstra可以看成是特殊的A*算法(所有估計距離為0)
設當前狀態為state,從起點到當前點的真實距離為d(state),從當前點到終點的估計距離為f(state),從當前點到終點的估計距離為g(state),則該算法的滿足條件為:
當終點第一次出隊時break,此時得到的就是最優解。
但不能保證除終點外其他點第一次出隊時得到的是最小值。
//算法正確性證明(反證法):
若終點第一次出隊時得到的距離dist不是最優解,在最優路徑上任取一點u,必有:
則。
與優先隊列(小根堆)性質矛盾,dist不可能在d(u)+f(u)之前出隊,可知假設不成立。那么終點第一次出隊時得到的距離dist一定是最優解。
AcWing 178. 第K短路
//當終點第k次出隊時break,此時得到的就是第K短路。
可用數學歸納法證明:與上面類似地,若終點第k次出隊時得到的距離dist不是第K短路,在第K短路上任取一點u,必有:
則
與優先隊列(小根堆)性質矛盾,dist不可能在d(u)+f(u)之前出隊,可知假設不成立。那么終點第k次出隊時得到的距離dist一定是第K短路。
AcWing 179. 八數碼
//八數碼問題有解的充分必要條件:
讀入的數字串的逆序對的數量是偶數。
數字的左右移動不會改變數字串的逆序對的數量,上下移動只是將某一數字移動到另兩個數字之后,逆序對改變的數量為2,不影響數字串的逆序對的數量的奇偶性。
八數碼問題的估價函數:當前狀態中每個數與它的目標位置的曼哈頓距離之和。
- 內部搜索:內部的某一部分能否走到另一部分,不回溯
- 外部搜索:將整體當成一個點,在整體與整體之間搜索,要回溯
DFS之連通性模型:
- Flood fill
- 圖與樹的遍歷
AcWing 1112. 迷宮
AcWing 1113. 紅與黑
DFS之搜索順序:
AcWing 1116. 馬走日
AcWing 1117. 單詞接龍
AcWing 1118. 分成互質組
//按照組合方式搜索,而不是按照排列方式搜索,這樣會少很多分支。避免搜過123之后又搜132
1.把某個數加到最后一組
2.新開一個組
只有當所有的數都不能加到最后一組時,才新開一個組。
DFS常見剪枝方法:
先考慮搜索順序,再考慮優化方法
如何進行剪枝操作須根據具體情況具體分析。
- 優化搜索順序
大部分情況下,我們應該優先搜索分支較少的節點。
- 排除等效冗雜
- 可行性剪枝
- 最優性剪枝
如果當前遞歸得到的答案已經大於最優值就直接return
- 記憶化搜索(DP)
AcWing 165. 小貓爬山
//將重量從大到小排序:
AcWing 166. 數獨
//剪枝:
- 用&來計算行、列、九宮格的交集,時間復雜度O(1)
- 用lowbit位運算優化來枚舉可選數字(有幾個1就循環幾次)
AcWing 167. 木棒
//從小到大枚舉木棒長度,從前往后依次拼木棒
木棍:題目給出的被砍斷的
木棒:由若干個木棍拼成
//剪枝:
- 枚舉sum的約數
- 優化搜索順序:從小到大枚舉
- 排除等效冗雜:
1) 按照組合數方式枚舉
2) 如果當前木棍加到當前棒中失敗了,則直接略過后面所有長度相等的木棍。
3) 如果是木棒的第一根木棍失敗了,則搜索該木棒一定失敗。
4) 如果是木棒的最后一根木棍失敗了,則搜索該木棒一定失敗。
AcWing 168. 生日蛋糕
//剪枝:
- 自底向上搜,從大到小先枚舉R,再枚舉H
- 預處理minv(u)和mins(u),可行性剪枝:v+minv(u)≤n,最優性剪枝:s+mins(u)﹤n
//max和min函數中的兩個變量類型要一致
迭代加深:
每次搜索都有一個層數上限:max_depth
適用於某些分支層數很深,但答案在較淺層的情況。
AcWing 170. 加成序列
//剪枝:
- 優先枚舉較大的數
- 排除等效冗余:用bool數組判斷是否枚舉過,避免出現例如1+4=2+3重復的情況
雙向DFS:
與雙向BFS類似,極大地提高了搜索效率。
AcWing 171. 送禮物
//用空間換時間,優先搜索較大的數。
//剪枝:
- 將所有物品按重量從大到小排序
- 先將前k件物品能湊出的所有重量打表,然后排序並判重
- 搜索剩下的n-k件物品的選擇方式,然后在表中二分出不超過w的最大值
//把一個vector去重:
把一個數組去重,元素存放在下標1~n:
IDA*:
配合迭代加深,更簡單、實用。
預估當前狀態到目標狀態所需的步數,若已超過步數上限則無需繼續搜索(剪枝)。
滿足條件(同A*算法):估價函數≤真實值
AcWing 180. 排書
//估價函數:
tot:錯誤的后繼數量
如圖所示,若將子串i移動到圖示位置,則數列中后繼發生改變的點共有三個(圖中用藍色標出)。
AcWing 181. 回轉游戲
//估價函數:8-cnt
cnt:中間八個格子中出現次數最多的數字的出現次數
//此題說明了打表的便利和重要性!!!