重複性剪枝
奇偶性剪枝
搜尋的過程最後會生成一顆搜尋樹
剪枝,顧名思義,就是通過一些判斷,砍掉搜尋樹上不必要的子樹,有時候,我們會發現某個結點對應的子樹的狀態都不是我們要的結果,那麼我們沒有必要對這個分支進行搜尋,砍掉這個子樹,就是剪枝
對於求最優解的一類問題,通常可以用最優性剪枝,比如在求解迷宮最短路的時候,如果發現當前的步數已經超過了當前最優解,那麼當前狀態的搜尋都是多餘的,因為這樣搜尋下去永遠都搜不到更優的解,通過這樣的剪枝,可以省去大量多餘的計算
此外,在搜尋是否有可行性解的過程中,一旦找到了一組可行解,後面所以的搜尋都不必再進行了,這算是最優性剪枝的乙個特例
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 高效性 正確性,顧名思義就是不能把通向正確的路徑剪去。準確性,則是盡可能多的剪去不會通向正確...