DFS深度優先搜尋中的標記問題

2021-09-10 18:43:50 字數 1577 閱讀 3067

同樣是象棋中馬的問題,有以下兩個具體情景:

問題1:給起點,走三步,求所有可能到達的點

問題2:給起點,不限制步數,求能否到達終點

上邊的dfs**

void

dfs(

int x,

int y,

int s)

} vis[x]

[y]=0;

}

下邊的dfs**

int

dfs(

int x,

int y)

vis[x]

[y]=1;

for(

int i =

0; i <

8; i++)}

return0;

}

限制步數的需要在本輪dfs結束(回溯)時取消vis標記。原因是可能這次標記的這個點是第三步到達的,沒有機會再往外擴充套件。但是下次再到這個點就是第一步或者第二步到達的,還有機會擴充套件,所以這一輪結束應該取消標記。

不限步數的不需要取消vis標記。原因是到達的每乙個點都進行了所有可能的擴充套件。即使下一次再到了這個點,跟這一次的結果也並無不同,所以不取消標記會大大節省時間(數量級的差別)

下面考慮迷宮問題中的標記

問題3:給定起點終點,求能否找到一條路徑

問題4: 給定起點終點,求可能的路徑個數

上邊的**

bool dfs

(int x,

int y)

vis[x]

[y]=1;

maze[x]

[y]=

'm';

for(

int i =

0; i <

4; i++)}

} vis[x]

[y]=0;

maze[x]

[y]=

'.';

return false;

}

下邊的**

void

dfs(

int i,

int j)

vis[i]

[j]=1;

for(

int k =

0; k <

4; k++)}

vis[i]

[j]=0;

}

第乙個問題需要取消標記原因是比如前後路徑中都路過了c,但是第一條是經由a到了c,第二條是由b到c,第一條不可以到達終點(比如路徑包圍了終點而a在終點和c中間),第二條就可以。因此c有多次到達的必要。第二個問題同理,經過同一點,但是從不同的點到這個點,也算不同路徑。

總結到達某點的路徑會影響結果的取消標記

不影響結果的留著標記

(某個點有多次到達的必要取消標記

至多只需到達一次留著標記

一次能把所有可能點擴充套件完畢的留著標記

否則取消標記

深度優先搜尋DFS(迷宮問題)

問題及 給出迷宮的圖紙和初始終點位置,用dfs求最小步數。include using namespace std int n,m,p,q,min 99999999 int a 51 51 book 51 51 void dfs int x,int y,int step 順時針 右下左上 int tx...

DFS深度優先搜尋 迷宮問題

首先我們用乙個陣列來儲存這個迷宮,用 1 代表障礙物,用 0 代表可通行的路 define n 22 int maze n n 假設我們現在處於 x,y 點 x y 指 maze 陣列的行 列 對於接下來的每一條路徑,我們只能乙個乙個地去嘗試 我們可以先往右走,直到走不通的時候再退回來,然後再去嘗試...

深度優先搜尋DFS

作為搜尋演算法的一種,dfs對於尋找乙個解的 np 包括npc 問題作用很大。但是,搜尋演算法畢竟是 時間複雜度是o n 的階乘級演算法,它的效率比較低,在資料規模變大時,這種演算法就顯得力不從心了。關於深度優先搜尋的效率問題,有多種解決方法。最具有通用性的是剪枝 prunning 也就是去除沒有用...