概述
深度優先搜索算法是搜索算法中常見的算法。深度優先搜索屬於圖算法的一種,英文縮寫爲DFS即Depth First Search,其過程簡要來說是對每一個可能的分支路徑深入到不能再深入爲止,而且每個節點只能訪問一次。
基本思路
深度優先遍歷圖的方法是,從圖中某頂點v出發:
- 訪問頂點v;
- 依次從v的未被訪問的鄰接點出發,對圖進行深度優先遍歷;直至圖中和v有路徑相通的頂點都被訪問;
- 若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,重新進行深度優先遍歷,直到圖中所有頂點均被訪問過爲止。
有些問題我們不能找出確切的數學模型,即找不出一種直接求解的辦法,解決這一類問題,我們一般採用搜索算法。搜索就是按照一定規則用問題的所有可能方法去試探,直到找到問題的解。對於問題的第一個狀態,叫初始狀態,要求的狀態叫目標狀態。因此,搜索就是把規則應用到初始狀態,在其產生的狀態中找到目標狀態。產生新狀態的過程叫做擴展。
搜索的要點:
- 初始狀態
- 重複產生新狀態
- 檢查新狀態是否爲目標狀態
基本框架
dfs(狀態)
–if 狀態 是 目標狀態then
dosomething
–else
for 每個新狀態
–if 新狀態合法
»dfs(新狀態)
主程序:
dfs(初始狀態)
用C、C++的僞代碼描述爲
void dfs(狀態)
{
if (狀態爲目標狀態)
{
處理解
}
else
{
for (每個新狀態)
{
if (新狀態合法)
{
dfs(新狀態);
}
}
}
}
int main()
{
dfs(初始狀態);
return 0;
}
八皇后
八皇后問題是一個以國際象棋爲背景的問題:如何能夠在 8×8 的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?爲了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。八皇后問題可以推廣爲更一般的n皇后擺放問題:這時棋盤的大小變爲n1×n1,而皇后個數也變成n2。而且僅當 n2 ≥ 1 或 n1 ≥ 4 時問題有解。
分析和詳解
8皇后的解爲92個。
#include <cstdio>
const int MAXN = 100;
int vis[MAXN][MAXN];//表示該點是否訪問過
int ans, n;
/**
* 判斷放置皇后的位置是否合法
* @parma r 皇后所在行
* @prama l 皇后所在列
* @return 合法返回true,非法返回false
*/
bool check(int r, int l)
{
//橫縱
for (int i = 0; i < n; ++i)
{
if (vis[r][i] || vis[i][l])
{
return false;
}
}
//左上角
for (int i = r-1, j = l-1; i >= 0 && j >= 0; --i, --j)
{
if (vis[i][j])
{
return false;
}
}
//左下角
for (int i = r+1, j = l-1; i < n && j >= 0; ++i, --j)
{
if (vis[i][j])
{
return false;
}
}
//右上角
for (int i = r-1, j = l+1; i >= 0 && j < n; --i, ++j)
{
if (vis[i][j])
{
return false;
}
}
//右下角
for (int i = r+1, j = l+1; i <n && j < n; ++i, ++j)
{
if (vis[i][j])
{
return false;
}
}
return true;
}
void dfs(int row)
{
if (row > n - 1)
{
//輸出解,X代表皇后位置
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (vis[i][j])
{
printf("X");
}
else
{
printf("O");
}
}
printf("\n");
}
printf("\n");
ans++;
}
//擴展
for (int i = 0; i < n; ++i)
{
if (check(row, i))
{
vis[row][i] = 1;
dfs(row + 1);
vis[row][i] = 0;
}
}
}
int main()
{
scanf("%d", &n);
dfs(0);
printf("The number of %d queen question : %d\n", n, ans);
return 0;
}