DFS
深度优先遍历四步走:
- 根据题意分层次
- 终点判断输出结果
- 结点判断是否被遍历过
- 回溯恢复现场
一、排列数字
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。现在,请你按照字典序将所有的排列方法输出。
算法分析
- 排列结果的每个位置为一层。
- 到达最底层后( u == n )输出排列 。
- 判断某个数字是否被使用过,若没有将该数字填入此层,并将状态值置为1。
- 每次整个 dfs 结束后需要将状态值置为0。
算法实现
#include<iostream>
using namespace std;
const int N=10;
int path[N];
int state[N];
int n;
void dfs(int u){
if(u==n){
for(int i=0;i<n;i++)
cout<<path[i]<<" ";
cout<<endl;
return ;
}
for(int i=1;i<=n;i++)
if(!state[i]){
path[u]=i;
state[i]=1;
dfs(u+1);
state[i]=0;
}
}
int main(){
cin>>n;
dfs(0);
return 0;
}
二、n - 皇后问题
n − 皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
算法分析
- 棋盘每一行为一层,这样保证了每行只有一个皇后。
- 到达最底层后( u == n )输出排列 。
- 判断同列和同斜线上有没有被使用过的位置,若没有将该数字填入此层,并将状态值置为 1 。
- 每次整个 dfs 结束后需要将状态值置为 0 。
算法实现
#include<iostream>
using namespace std;
const int N=20;
int col[N],dg[2*N],udg[2*N];
char g[N][N];
int n;
void dfs(int u){
if(u==n){
for(int i=0;i<n;i++)
cout<<g[i]<<endl;
cout<<endl;
return ;
}
for(int i=0;i<n;i++)
if(!col[i]&&!dg[i+u]&&!udg[n-u+i]){
g[u][i]='Q';
col[i]=dg[i+u]=udg[n-u+i]=1;
dfs(u+1);
col[i]=dg[i+u]=udg[n-u+i]=0;
g[u][i]='.';
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]='.';
dfs(0);
return 0;
}
LeetCode又做了一次,不太熟悉力扣的写法,贴一下。
class Solution {
public:
vector<vector<string>> res;//装棋盘用的
vector<string> g;//棋盘,记得要初始化
vector<int> col,dg,udg;//列,斜线,反斜线,记得要初始化
void dfs(int u,int n){
if(u==n){
res.push_back(g);
return;
}
for(int i=0;i<n;i++){
if(!col[i]&&!dg[i+u]&&!udg[n-i+u]){
col[i]=dg[i+u]=udg[n-i+u]=1;
g[u][i]='Q';
dfs(u+1,n);
col[i]=dg[i+u]=udg[n-i+u]=0;
g[u][i]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
g=vector<string>(n,string(n,'.'));
col=vector<int>(n);
dg=udg=vector<int>(n*2);
dfs(0,n);
return res;
}
};