void
dfs(
int x)
//關於傳入引數問題,根據題意而定,看在題目執行的過程中,哪些是在變得
if(目前已經沒有必要進行下去的條件)
//剪枝操作
//如果傳入的條件,還需要繼續搜下去,分析每一種情況後面跟哪些情況,然後迴圈,每個情況(注意前提:得符合題意)都深搜一下
for(
int i=
1;i<=每種情況數;i++)if
(滿足進一步搜尋條件)
//判斷是否合理}}
}
拿最經典的八皇后問題解釋dfs,正常情況下,如果有乙個6*6的棋盤,在第一行,選擇落子,不考慮規則限制,我們有6種落子方式。
第二行,有1 2 3 4 5 6,6種落子方式。以此類推,6的6次方種情況。
但現在由於規則限制,跟bfs一樣根據流程想出乙個樹出來。指需要按照規則取捨一下那些結點有,哪些沒有即可,搜尋方式上採取遞迴+回溯
從最終結果上,呈現出來的是從根節點一條路走到底,然後撤回底點的上乙個結點,撤回後能走另乙個,就走另乙個
dfs傳入的引數一定要能表示出每個情況的狀態
p1219 八皇后 題目鏈結
乙個如下的 6×6 的跳棋棋盤,有六個棋子被放置在棋盤上,使得每行、每列有且只有乙個,每條對角線(包括兩條主對角線的所有平行線)上至多有乙個棋子。
上面的布局可以用序列 2 4 6 1 3 5 來描述,第 ii 個數字表示在第 ii 行的相應位置有乙個棋子,如下:
行號 1 2 3 4 5 6
列號 2 4 6 1 3 5
這只是棋子放置的乙個解。請編乙個程式找出所有棋子放置的解。
並把它們以上面的序列方法輸出,解按字典順序排列。
請輸出前 33 個解。最後一行是解的總個數。
輸入格式
一行乙個正整數 nn,表示棋盤是 n \times nn×n 大小的。
輸出格式
前三行為前三個解,每個解的兩個數字之間用乙個空格隔開。第四行只有乙個數字,表示解的總數。
輸入輸出樣例輸入6
輸出2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4說明/提示
【資料範圍】
對於 100%100% 的資料,6 ≤n≤13。
思路就是深搜加回溯,技巧就是對於斜對角線上面是否有結點的判別,算一下就知道,左下到右上斜對角線i+j=固定值,左上到右下i-j+n=固定值
按照深搜的思想進行分析,在題目執行過程中,所腦補出的樹形結構,什麼在改變。開始乙個棋盤上面,什麼都沒放,在第一行上可以放1 2 3 4 5 6位置。
如果選取1,對1深搜結果如下,選擇2,3都一樣。
下一步,第二行,1已經被放過,可以放2 3 4 5 6,放2位置不行,3位置可以
下一步,從3行2列開始。。。。。。。
過程中可以發現,改變是行數,第一行每個可能深搜第二行,第二行每個可能深搜第三行。
ac**
#include
using
namespace std;
int p[
100]
;//儲存路徑
int visy[
100]=;
//記錄列是否訪問
int vxie1[
100]=;
//記錄左下到右上斜線是否訪問
int vxie2[
100]=;
//左上到右下
int n;
//n*n棋盤
int total=0;
//記錄搜尋到結果總數
void
dfs(
int x)
//如果x=n表示已經搜到最後一行,total++,一條路走到盡頭
//否則這一行,有n種情況,如果符合題意,每個情況繼續深搜
for(
int j=
0;j}int
main()
資源限制
時間限制:1.0s 記憶體限制:256.0mb
問題描述
n個人參加某項特殊考試。
為了公平,要求任何兩個認識的人不能分在同乙個考場。
求是少需要分幾個考場才能滿足條件。
輸入格式
第一行,乙個整數n(1這題因為我比較笨,所以想了很久才想通。同樣是分析題目進行過程腦補出樹或圖。
第一步。所有房間都是空的,放裡面放人,放第乙個人
第二步。放第二個人,如果與第乙個房間所有人沒關係,放第乙個房間,否則新開乙個房間,放進去。
第三步,放第三個人,如果1,2房間不能放,開乙個房間放到3號房間,否則放在1或2房間
第四步。。。。
分析過程可以看出,每次房間數是在變化,每次放的人的編號也在變化。意思就是樹的每個點,都包含我現在放入編號幾,我用了多少個房間,在每個點裡搜出最佳點。
ac**
#include
using
namespace std;
int n,m,min_num;
int mp[
102]
[102]=
};int r[
102]
[102]=
};void
dfs(
int x,
int num)
//如果已經安排完,比較後更新最少房間數
//八皇后一樣到x行,都會有n種情況。對於此題到達分配編號x,有num個房間
for(
int i=
1;i<=num;i++)}
//找不到合適的房間,就開乙個新的房間繼續深搜,**就是把流程寫了一遍
r[num+1]
[0]=x;
dfs(x+
1,num+1)
; r[num+1]
[0]=
0;}int
main()
dfs(1,
0);printf
("%d\n"
,min_num)
;}
p1605 迷宮題目位址
題目背景
給定乙個n*m方格的迷宮,迷宮裡有t處障礙,障礙處不可通過。給定起點座標和終點座標,問: 每個方格最多經過1次,有多少種從起點座標到終點座標的方案。在迷宮中移動有上下左右四種方式,每次只能移動乙個方格。資料保證起點上沒有障礙。
題目描述
無輸入格式
第一行n、m和t,n為行,m為列,t為障礙總數。第二行起點座標sx,sy,終點座標fx,fy。接下來t行,每行為障礙點的座標。
輸出格式
給定起點座標和終點座標,問每個方格最多經過1次,從起點座標到終點座標的方案總數。
輸入輸出樣例
輸入 #1 複製
2 2 1
1 1 2 2
1 2輸出 #1 複製
1說明/提示
【資料規模】
1≤n,m≤5
思路這道題也可以用bfs做,每個結點有四處走向,不斷地擴散,找到終點,返回
但是記錄能有幾條路比較麻煩
用dfs思路和前兩題一樣,按照題目過程腦補出樹
第一步,在起點,有4種情況,如果可以,上下左右都深搜一下(如果選擇深搜右)
第二步,起點的右節點為起點,上下左右如果可以的話,都深搜(如果可以還選擇右)
第三步,起點的右的右,上下左右,都深搜,。。。。還選右的話
如果題意允許,就一直講走完到了終點,遞迴出口讓total++就行
ac**
就沒有注釋太多了,跟前面差不多
#include
using
namespace std;
int n,m,t,total=0;
//n行,m列,t個障礙物
int sx,sy,x2,y2;
//起點x,y,終點x,y
int mp[10]
[10]=
};int vis[10]
[10]=
};int dir[4]
[2]=
,,,}
;void
dfs(
int x,
int y)
for(
int i=
0;i<
4;i++)}
}int
main()
dfs(sx,sy)
;printf
("%d\n"
,total)
;}
總結完畢! 深度優先搜尋(DFS)例題
dfs概念 它從某個狀態開始,不斷地轉移狀態直至無法轉移,然後回退到前一步的狀態,繼續轉移其他狀態,如此不斷重複,直至找到最終的解。解題利用的是 遞迴函式。例題 dfs 例題 給定整數a1,a2,a3.an,判斷是否能夠從中抽出幾個整數使得它們的和剛好為k int a max int n,k boo...
深度優先遍歷DFS
本文章 中的圖用鄰接矩陣來表示,所以演算法複雜度為o v 2 如果用鄰接表來表示,那麼演算法的複雜度為o v e dfs可用來判斷圖中是否有環,展現無向圖中的連通分支。通過dfs,形成乙個由多棵深度優先樹所組成的深度優先森林。將原先圖中的邊新增到該森林之後,可以將所有邊定義為以下四類 1.樹邊 森林...
深度優先遍歷(DFS)
深度優先搜尋是一種列舉所有完整路徑以遍歷所有情況的搜尋方法。使用遞迴可以很好的實現深度優先遍歷,因此,只能說遞迴是實現深度優先遍歷的一種實現方式。給定乙個序列,列舉這個序列所有的子串行 例如子串行包含,選擇最優子串行,使它的某個特徵是所有子串行中最優的。這個問題也就是從n個整數中,選擇k個數的所有方...