同樣是象棋中馬的問題,有以下兩個具體情景:
問題1:給起點,走三步,求所有可能到達的點
問題2:給起點,不限制步數,求能否到達終點上邊的dfs**
下邊的dfs**void
dfs(
int x,
int y,
int s)
} vis[x]
[y]=0;
}
限制步數的需要在本輪dfs結束(回溯)時取消vis標記。原因是可能這次標記的這個點是第三步到達的,沒有機會再往外擴充套件。但是下次再到這個點就是第一步或者第二步到達的,還有機會擴充套件,所以這一輪結束應該取消標記。int
dfs(
int x,
int y)
vis[x]
[y]=1;
for(
int i =
0; i <
8; i++)}
return0;
}
不限步數的不需要取消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;
}
第乙個問題需要取消標記原因是比如前後路徑中都路過了c,但是第一條是經由a到了c,第二條是由b到c,第一條不可以到達終點(比如路徑包圍了終點而a在終點和c中間),第二條就可以。因此c有多次到達的必要。第二個問題同理,經過同一點,但是從不同的點到這個點,也算不同路徑。void
dfs(
int i,
int j)
vis[i]
[j]=1;
for(
int k =
0; k <
4; k++)}
vis[i]
[j]=0;
}
總結到達某點的路徑會影響結果的取消標記
不影響結果的留著標記
(某個點有多次到達的必要取消標記
至多只需到達一次留著標記
一次能把所有可能點擴充套件完畢的留著標記
否則取消標記
)
深度優先搜尋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 也就是去除沒有用...