DFS深度优先搜索 全排列 n皇后
递归实现排列型枚举
题目:
把 这 n(n<10)个整数排成一行后随机打乱顺序,按字典序输出所有可能的次序。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
int path[N];//记录当前路径,当前的情况
bool s[N];//记录当前数字是否被用过。
int n;
void dfs(int u){
if(u==n){
for(int i=0;i<n;i++) cout<<path[i]<<" ";//如果走到了头那么就输出答案
puts("");
return;
}
for(int i=1;i<=n;i++){
if(!s[i]){
path[u]=i;
s[i]=true;//注意这里是用过了标记的true;
dfs(u+1);
path[u]=0;//恢复现场,返回上一步,恢复上一步原来的样子
s[i]=false;
}
}
}
int main(){
cin>>n;
dfs(0);
}n皇后问题
n皇后问题
有两种顺序可以枚举。
代码:
//按全排列的顺序搜索,时间复杂度,n*n!;
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n;
char g[N][N];
bool col[N],dg[N],udg[N];//记录有没有被放过皇后,列,主副对角线。
void dfs(int u){
if(u==n){
for(int i=0;i<n;i++) puts(g[i]);//如果符合输出答案
puts("");
return;
}
for(int i=0;i<n;i++){//按行搜索排列
if(!col[i]&&!dg[u+i]&&!udg[n-u+i]){//确保这一列、主对角线、副对角线上都没有被选过
g[u][i]='Q';//这里u+i,n-u+i,表示截距。
col[i]=dg[u+i]=udg[n-u+i]=true;
dfs(u+1);
g[u][i]='.';//恢复现场
col[i]=dg[u+i]=udg[n-u+i]=false;
}
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
g[i][j]='.';
}
}
dfs(0);
}枚举每一个格子的代码:
//按一个一个格子的顺序搜索,时间复杂度2的n方次,指数级别。
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n;
char g[N][N];
bool row[N],col[N],dg[N],udg[N];
void dfs(int x,int y,int s){
if(y>n) return;
if(y==n) y=0,x++;//如果y超过了边界换行,行数加1,y直接到下一行开头为0;
if(x==n){
if(s==n){
for(int i=0;i<n;i++) puts(g[i]);
puts("");
}
return;
}
g[x][y]='.';
//两种选择
dfs(x,y+1,s);//1.不放皇后,直接递归到下一个,递归由里往外执行
//2.放皇后,则判断是否放过
if(!row[x]&&!col[y]&&!dg[x+y]&&!udg[x-y+n]){//判断行列、住副对角线是否被放过皇后
g[x][y]='Q';
row[x]=col[y]=dg[x+y]=udg[x-y+n]=true;
dfs(x, y + 1, s + 1);
g[x][y] = '.';//恢复现场
row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
g[i][j]='.';
}
}
dfs(0,0,0);
}
美团成长空间 2637人发布
查看21道真题和解析