深搜的剪枝策略筆記

2021-10-17 23:13:44 字數 2837 閱讀 5200

重複性剪枝

奇偶性剪枝

搜尋的過程最後會生成一顆搜尋樹

剪枝,顧名思義,就是通過一些判斷,砍掉搜尋樹上不必要的子樹,有時候,我們會發現某個結點對應的子樹的狀態都不是我們要的結果,那麼我們沒有必要對這個分支進行搜尋,砍掉這個子樹,就是剪枝

對於求最優解的一類問題,通常可以用最優性剪枝,比如在求解迷宮最短路的時候,如果發現當前的步數已經超過了當前最優解,那麼當前狀態的搜尋都是多餘的,因為這樣搜尋下去永遠都搜不到更優的解,通過這樣的剪枝,可以省去大量多餘的計算

此外,在搜尋是否有可行性解的過程中,一旦找到了一組可行解,後面所以的搜尋都不必再進行了,這算是最優性剪枝的乙個特例

n,m分別為迷宮的行數和列數,maze記錄迷宮的地形,vis記錄dfs過程中當前位置是否被訪問過,dir表示每次列舉的四個方向,ans記錄當前到達終點的最小的步數,初始值為乙個較大的數

#include

#include

#include

using

namespace std;

int n, m;

string maze[

110]

;bool vis[

100]

[100];

int dir[4]

[2]=

,,,}

;int ans =

10000

;boolin(

int x,

int y)

void

dfs(

int x,

int y,

int step)

if(maze[x]

[y]==

't')

vis[x]

[y]=1;

for(

int i =

0; i <

4; i++)}

vis[x]

[y]=0;

}int

main()

int x, y;

for(

int i =

0; i < n; i++)}

}dfs

(x, y,0)

; cout << ans << endl;

}

對於某一些特定的搜尋方式,乙個方案可能會被搜尋很多次,這樣是沒必要的

比如:給定n個整數,要求選出k個數,使得選出來的k個數的和為sum

如果搜尋方式是每次從剩下的數里選乙個數,乙個搜到第k層,那麼1,2,3這個選取方法能被搜尋到6次,這是沒必要的,我們只需要關注選出來的數的順序,所以這裡可以用重複性剪枝

#include

using

namespace std;

int n, k, sum, ans;

int a[40]

;bool xuan[40]

;void

dfs(

int s,

int cnt,

int pos)

if(s == sum && cnt == k)

for(

int i = pos; i < n; i++)}

}int

main()

ans =0;

dfs(0,

0,0)

; cout << ans << endl;

return0;

}

有乙個nm大小的迷宮,s表示起點,d表示出口,x表示牆壁,. 表示平地。你需要從s出發走到d。每次只能上下左右相鄰的位置移動,並且不能走出地圖,也不能走出牆壁

每次移動消耗1時間,走過路都會崩塌,因此不能回頭或者原地不動。現在已知出口的大門會在t時間開啟,判斷在0時間從起點出發能否逃離迷宮

可將nm的網路黑白兩色,我們計每個格仔的行數和列數之和為x,如果x為偶數,那麼格仔就是白色,反之為黑色。容易發現相鄰的兩個格仔的顏色肯定不相同,也就是說每走一步顏色都不相同。更普遍的結論為:走奇數步會改變顏色,走偶數步顏色不變

那麼如果起點和終點的顏色相同,而t是奇數的話,就不可能逃離迷宮,如果起點和終點的顏色不一樣,而t是偶數的話,也不能逃離迷宮,遇到這兩種情況,就不用dfs了,直接輸入no

這樣的剪枝就是奇偶性剪枝,本質也屬於可行性剪枝

#include

using

namespace std;

const

int n =10;

int n, m, t;

char mat[n]

[n];

bool vis[n]

[n];

int dx[4]

=;int dy[4]

=;bool ok;

void

dfs(

int x,

int y,

int t)

if(t ==

't')

return;}

vis[x]

[y]=

true

;for

(int i =

0; i <

4; i++

)dfs

(tx, ty, t +1)

;}vis[x]

[y]=

false;}

intmain()

int sx, sy, ex, ey;

for(

int i =

0; i < n; i++)if

(mat[i]

[j]=

'd')}}

if((sx + sy + ex + ey + t)%2

!=0)else

else

}}

深搜的剪枝

深搜前面已經講過,對於剪枝,就是把沒必要的步驟進行if特判剪枝,用好了可以大大的優化複雜度 這裡就根據兩個例題來講吧 詳情見 include include include intn,k int f 210 7 int main printf d n f n k 輸出最大值 return0 詳情見 ...

深搜優化剪枝

之前做過不少深搜題,很多tle,所以剪枝很重要,如何 未雨綢繆 避免不必要的搜尋樹分支?例題 將整數n分成k份,且每份不能為空,任意兩份不能相同 不考慮順序 例如 n 7,k 3,下面三種分法被認為是相同的。1,1,5 1,5,1 5,1,1 問有多少種不同的分法。輸出乙個整數,即不同的分法。由題意...

深搜剪枝小結

深度優先搜尋,俗稱深搜,即dfs,是乙個常用並且基礎的演算法和思想。但是搜尋演算法的時間複雜度往往很大,是oi不被允許的。所以對於深搜的優化最實用和基礎的乙個方法就是剪枝。三原則 1 正確性 2 準確性 3 高效性 正確性,顧名思義就是不能把通向正確的路徑剪去。準確性,則是盡可能多的剪去不會通向正確...