DFS定義
DFS(Depth-First-Search)深度優先搜尋演算法,是搜尋演算法的一種。是一種在開發爬蟲早期使用較多的方法。它的目的是要達到被搜尋結構的葉結點 。
特點
每次深度優先搜尋的結果必然是圖的一個連通分量。深度優先搜尋可以從多點發起。如果將每個節點在深度優先搜尋過程中的“結束時間”排序(具體做法是建立一個list,然後在每個節點的相鄰節點都已被訪問的情況下,將該節點加入list結尾,然後逆轉整個連結串列),則我們可以得到所謂的“拓撲排序”,即topological sort.
當然,當人們剛剛掌握深度優先搜尋的時候常常用它來走迷宮。事實上我們還有別的方法,那就是廣度優先搜尋 (BFS)。狀態(state):狀態是指問題求解過程中每一步的狀況。
經典演算法過程
圖的深度遍歷原則:
1 如果有可能,訪問一個領接的未訪問的節點,標記它,並把它放入棧中。
2 當不能執行規則 1 時,如果棧不為空,則從棧中彈出一個元素。
3 如果不能執行規則 1 和規則 2 時,則完成了遍歷。
典型例項(兵臨城下)
該題目是樂視的面試程式設計題
盧卡斯的驅逐者大軍已經來到了赫柏的卡諾薩城,赫柏終於下定決心,集結了大軍,與驅逐者全面開戰。 盧卡斯的手下有6名天之驅逐者,這6名天之驅逐者各賦異能,是盧卡斯的主力。 為了擊敗盧卡斯,赫柏必須好好考慮如何安排自己的狂戰士前去迎戰。 狂戰士的魔法與一些天之驅逐者的魔法屬性是相剋的,第i名狂戰士的魔法可以剋制的天之驅逐者的集合為Si(Si中的每個元素屬於[0,5])。 為了公平,兩名狂戰士不能攻擊同一個天之驅逐者。 現在赫柏需要知道共有多少種分派方案。 例: S1={01},S2={23},代表編號為0的狂戰士的魔法可以剋制編號為0和編號為1的天之驅逐者,編號為1的狂戰士的魔法可以剋制編號為2和編號為3的天之驅逐者,共有四種方案:02,03,12,13。 02---代表第一個狂戰士負責編號為0的驅逐者,第二個狂戰士負責編號為2的驅逐者; 03---代表第一個狂戰士負責編號為0的驅逐者,第二個狂戰士負責編號為3的驅逐者; 12---代表第一個狂戰士負責編號為1的驅逐者,第二個狂戰士負責編號為2的驅逐者; 13---代表第一個狂戰士負責編號為1的驅逐者,第二個狂戰士負責編號為3的驅逐者; S1={01},S2={01},代表編號為0的狂戰士的魔法可以剋制編號為0和編號為1的天之驅逐者,編號為1的狂戰士的魔法可以剋制編號為0和編號為1的天之驅逐者,共有兩種方案:01,10。
輸入描述:
多組測試資料,請處理到檔案結束。
對於每組測試資料:
第一行為一個整數N,代表狂戰士的數量。
第二行為N個字串,第i個字串表示第i個狂戰士能夠剋制的天之驅逐者的集合。
保證:
1<=N<=6,1<=每個字串的長度<=6,且每個字元都是0~5中的一個數字。
輸出描述:
輸出一個整數,代表分配方案數
輸入例子:
2 01 23 2 01 01 3 3 015 5
輸出例子:
4 2 2
分析:
1.對於這種遍歷的問題,考慮採用經典的DFS,設定一個輔助的陣列(題目要求不能兩個人打一個),來記錄是否是否是唯一的。
2.判斷每個分支的截止條件,通過遞迴和迴圈完成遍歷。
程式碼:
public class Main {
private static int ans;
public static int getAns(String[] str, int n) {
ans = 0;
int[] vis = {0, 0, 0, 0, 0, 0};
dfs(str, vis, n, 0);
return ans;
}
public static void dfs(String[] str, int[] vis, int n, int p) {
if (p == n) {
ans++;
return ;
}
for (int i = 0; i < str[p].length(); i++) {
if (vis[str[p].charAt(i) - '0'] == 0) {
vis[str[p].charAt(i) - '0'] = 1;
dfs(str, vis, n, p + 1);
vis[str[p].charAt(i) - '0'] = 0;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(new BufferedInputStream(System.in));
while (in.hasNext()) {
int n = in.nextInt();
String[] str = new String[n];
for (int i = 0; i < n; i++) {
str[i] = in.next();
}
int ans = getAns(str, n);
System.out.println(ans);
}
in.close();
}
}
複製程式碼