图论-DFS

从一开始的基础到慢慢进入数论,中间也算是写了一点点代码了。从今天开始就要开始进入图论了,不然一直在基础层面上,数据结果的知识一点都没有去进行涉及。虽然还有很多的内容没有更新完,但是现在还是开始去交叉的进行吧,之前上过数据结构的课,但是coding的能力很弱,现在补一下吧。也算是对这个知识点进行实际的操作吧。

DFS:深度优先搜索,尽量往深处进行,树的前中后遍历从某种意义上来说算是深度优先搜索
BFS:广度优先搜索,从广度上进行出发(类比于水),数的层序遍历其实就是类似于BFS。

这里用树去进行类比

从数据结构上看:DFS使用栈stack,BFS使用的是队列
从空间复杂度上看:DFS的时间复杂度O(n),BFS的时间复杂度为O( 2 n 2^n 2n)

对比:
BFS存在最短路的概念,因为是按层去进行查找。
DFS不具有最短路的性质,因为是从深度从进行出发。

DFS和BFS可能涉及回溯和剪枝

引入例题:

#include 
#include 
using namespace std;
//DFS俗称暴力搜索,+回溯,回溯之后一定要恢复现场 
const int N=10;
//记录方案 
int path[N];//记录树的路径 
int n;
bool st[N];//表示哪些数被用掉了,用掉了就是true 。
//此时st[N]都是false 
void dfs(int u){
	if(u==n)//此时表示所有的位置填满了 
	{
		for(int i=0;i<n;i++){
			cout<<path[i]<<" ";
		}
		puts("");//换行 
		return;
	}
	//说明没有访问到最底层,数字没有填充完 
	for(int i=0;i<n;i++){
		//!st[i] :表示数没有被用过 
		if(!st[i]){
			path[u]=i;
			st[i]=true;//标示的是数字i被用过了 
			dfs(u+1);//递归到下一层 
			st[i]=false;//回溯的过程、这个很关键 
		}
	}
} 

#include 
using namespace std;
int main(){
	
	cin>>n;
	dfs(0);//从第0开始看,也就是根节点 
	return 0;
}

DFS的另一个应用:N皇后的问题,顺便复习一下递归。
引入例题:
Acwing-843. n-皇后问题
leetcode-51. N皇后
其实这两个题目一模一样:
这里通过三个方法:
前两个方法采用深度优先搜索:
就是稍微格式上改了一点

#include 
using namespace std;
const int N=20;
int n;
bool col[N],N_dg[N],P_dg[N];
char oc[N][N];

//深搜的过程
void dfs(int u){
    if(u==n){
        for(int i=0;i<n;i++){
            puts(oc[i]);
        }
        puts("");
        return;
    }
    for(int i=0;i<n;i++){
        //回溯+剪枝
        if(!col[i]&&!N_dg[u+i]&&!P_dg[n-u+i]){
            oc[u][i]='Q';
            col[i]=N_dg[u+i]=P_dg[n-u+i]=true;
            dfs(u+1);
            col[i]=N_dg[u+i]=P_dg[n-u+i]=false;
            oc[u][i]='.';
        }
    }
}
int main(){
    cin>>n;   
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            oc[i][j]='.';
        }           
    }
    //进行dfs深搜
    dfs(0);
    return 0;
}

leetcode的题解:

如何从行列去进行深搜呢?常规思路,就像是我们下期一样。

#include 
using namespace std;
const int N=20;

bool col[N],row[N],N_dg[N],P_dg[N]; 
char oc[N][N];
int n;//n表示皇后的个数,多少行就存在多少个皇后 
//s标示的是皇后的个数 
void dfs(int x,int y,int s){
	//两种边界条件假设 
	if(y==n) y=0,x++;
	if(x==n){
		if(s==n){
			for(int i=0;i<n;i++){
				puts(oc[i]);
			}
			puts("");
		}
		return;
	} 
	
	//基于两种选择,放皇后和不放皇后 
	
	//不放皇后,递归到下一个格子,也就是下一列 
	dfs(x,y+1,s);
	//放皇后 .条件:这一行,这一列,对角线都不允许放皇后 
	if(!row[x]&&!col[y]&&!N_dg[x+y]&&!P_dg[x-y+n]){
		oc[x][y]='Q';
		//条件成立,更新条件,放皇后
		row[x]=col[y]=N_dg[x+y]=P_dg[x-y+n]=true;
		//递归到下一层
		dfs(x,y+1,s+1);
		row[x]=col[y]=N_dg[x+y]=P_dg[x-y+n]=false;
		oc[x][y]='.'; 
	} 
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			oc[i][j]='.';//为了符合格式将每一个二维数组全部填成. 
		}
	}
	//从左上角开始去进行搜索,并记录有多少个皇后 
	//前两个参数为某行某列,第三个参数是皇后个数 
	dfs(0,0,0);
	return 0;
}

你可能感兴趣的:(算法)