我們在bfs時,要從起點,搜遍整顆搜尋樹,然後找到終點,整個過程大概是乙個如下的結構
我比較懶,所以圖非常簡陋。
最上面的節點表示起點,最下面的點表示終點。
我們正常的bfs是從起點一路向下搜到終點,這樣要擴充套件不少的狀態,耗費不少的時間。
這樣我們想我們其實可以從起點和終點同時開始搜,起點和終點同時向外擴充套件一步,當兩個搜尋路徑交會時,結束搜尋。
這樣我們可以省去一半的時間。
我們用兩個佇列分別表示起點的擴充套件和終點的擴充套件
例題:常見的迷宮問題,0表示有障礙,1表示無障礙,假設沒有無法走到的情況,求最少需要多少步
非常顯然的bfs
1 #include2view codeusing
namespace
std;
3const
int maxn = 3030;4
struct
node q1[maxn], q2[maxn];7//
int stx, sty, edx, edy;
8int
a[maxn][maxn];
9int
n, m;
10int tail1 = 0, head1 = 1, tail2 = 0, head2 = 1;11
//int dx[9] = ;
12//
int dy[9] = ;
13//
int vis[maxn][maxn];
14int dx[5] = , dy[5] = ;
15int
st[maxn][maxn], ed[maxn][maxn];
16int
stept[maxn][maxn], stepe[maxn][maxn];
17bool flag = 0;18
int ans = 0;19
20 inline int
read()
27while
(isdigit(ch))
31return x *y;32}
3334
intmain()
56 st[xx][yy] = 1
;57 q1[++tail1].x =xx;
58 q1[tail1].y =yy;59}
60}61if(flag == 1) break;62
for(int i = 0; i < 4; ++i)
73 ed[xx][yy] = 1
;74 q2[++tail2].x =xx;
75 q2[tail2].y =yy;76}
77}78if(flag == 1) break;79
}80 cout << ans << '\n'
;81return0;
82 }
在一些需要搜尋的情況下,使用dfs會因為搜尋樹的深度太深,加上結果比較靠後,而導致耗費巨大的時間,而如果使用bfs,則會因為要儲存大量狀態而耗費大量的空間
這個時候我們可以使用迭代加深搜尋。
簡而言之就是我們人為規定乙個搜尋深度,每次到限定的搜尋深度時停止。
比如說第一次我們規定搜尋深度為1,我們搜尋一層,結束
第二次我們規定搜尋深度為2,我們搜尋兩層,結束
這樣我們會發現我們絕對會出現大量的重複計算,但是這對於我們直接進行dfs在搜尋樹上跑所需要的時間來說,是少得多的,這樣這個演算法就顯得優秀了
例題1:
這題我們可以發現直接dfs我們似乎無法下手,我們可以腦洞一下,構造出一顆搜尋樹(當然我在口胡)
我們可以發現從第乙個分叉向下擴充套件,可能會擴充套件的非常深都沒有找到答案。用bfs我們固然可寫,但是會耗費不小的空間。
這樣我們就可以迭代加深搜尋。
需要注意的是黑白棋是交替下的,而且題面並沒有明確說是黑棋先下還是白棋先下
我們需要對黑先和白先分別進行計算
1 #include2view codeusing
namespace
std;
3const
int maxn = 6;4
const
int deep = 1000000000;5
int ox1, oy1, ox2, oy2;//
分別記錄兩個空白地帶的座標
6char
ch[maxn];
7char
a[maxn][maxn];
8bool flag = 0;9
int dx[5] = , dy[5] = ;
10int ans = 0;11
12 inline bool
check()
17if(a[1][1] == a[2][2] && a[1][1] == a[3][3] && a[1][1] == a[4][4]) return
1;//
判斷是否存在由左上到右下角的四子連棋
18if(a[1][4] == a[2][3] && a[1][4] == a[3][2] && a[1][4] == a[4][1]) return
1;//
判斷是否存在由右上到左下角的四子連棋
19return0;
20}2122 inline bool able(int x, int y, int
dad)
2425
bool deepdfs(int x1, int y1, int x2, int y2, char pre, int
begin)
30for(int i = 0; i < 4; ++i)
38 xx = x2 +dx[i];
39 yy = y2 +dy[i];
40if
(able(xx, yy, pre)) 45}
46return0;
47}4849
intmain()
59else
if(flag) ox2 = i, oy2 =j;60}
61}62}
63/*
for(uint i = 1; i <= 4; ++i)
*/68
for(ans = 1; ans <= deep; ++ans)
74 cout << ans << '\n'
;75return0;
76 }
全文搜尋的一些理論總結2
1.通過正則實現 p re.compile abc p.findall abc selpabcdslfabceflabc abc abc abc abc 2.通過trie樹實現 trie樹,又稱字典樹,單詞查詢樹或者字首樹,是一種用於快速檢索的多叉樹結構。trie一詞來自retrieve,發音為 t...
一些記憶化搜尋
題目鏈結 題面較長,這裡不放截圖了 比較典型的記憶化搜尋題,如果不記憶化的話將有大量重複計算嚴重影響效率。這個用dp也比較複雜,因為這裡涉及到一些路徑可能往回走。這裡每次儲存起始點能夠走到最底層的左端點和右端點 這裡可以證明如果下面一排全能走到那麼每個起始點所覆蓋的區間一定是連續的,想一想,為什麼?...
搜尋的一些謂詞
搜尋框的一些謂詞 nspredicate predicate nspredicate predicatewithformat username beginswith c searchstring 搜尋username為searchstring的物件 beginswith 查詢首字元符合條件的 end...