DFS:深度优先搜索
DFS:一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
优先考虑深度 一条路径结束后再考虑下一条
一般搜索(栈)与递归搜索的区别
1- 2
| /
3 — 4
一般搜索:先找到每个出边所对应的未被处理的点(2,3同时被1发现并入栈),在进行依次进行深度搜索即1 24 3或1 3 24但不可能是1234
递归搜索:依次找到每个出边所对应的未被处理的点(2,3先后被发现),故:可能1先发现2,2发现3,4, 可能是12 3 4
基本操作
DFS(v) // v 可以是图中的一个顶点,也可以是抽象的概念,如 dp 状态等。
在 v 上打访问标记
for u in v 的相邻节点
… if u 没有打过访问标记 then
… … DFS(u)
… … … end
… … end
… end
全排列问题
题意:给一个数字n,输出1~n的全排列
#include<iostream>
using namespace std;
int a[100];//记录顺序
int vis[100];//标记访问
int n;
void dfs(int x){
if(x>n){//搜索结束,输出
for(int i=1;i<=n;i++){
printf("%d",a[i]);
}
printf("\n");
}
else{
for(int i=1;i<=n;i++){
if(vis[i]==0){//若没有访问过,则访问
a[x]=i;//记录数字
vis[i]=1;//标记已访问
dfs(x+1);//递归搜索
vis[i]=0;//回溯
}
}
}
return;//返回上一级
}
int main(){
while(~scanf("%d",&n)){
dfs(1);
}
return 0;
}
迷宫(POJ 3984简化版)
题意
0为可走的路 1为墙,找到从左上角到右下角的路(找到即可,不需最短)
0 1 0 1 0
0 1 0 1 1
0 0 0 0 1
0 1 1 0 1
0 1 0 0 0
代码1(找到即可,不需最短)
int a[100][100];//迷宫
int vis[100][100];//访问
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool flag=false;
int n;//规格n*n
void dfs(int x,int y){
if(flag==true){//如果已经找到就不需要再找了
return;
}
if(x==n&&y==n){//如果到达目的地,能够找到这样的路,flag为true,停止递归
flag=true;
return;
}
vis[x][y]=1;
for(int i=0;i<4;i++){//向四周找是否有路可走
int nxt_x=x+dx[i];
int nxt_y=y+dy[i];
if(nxt_x<1||nxt_y<1||nxt_x>n||nxt_y>n){//超过n*n边界,不进行递归
continue;
}
if(a[nxt_x][nxt_y]==0&&vis[nxt_x][nxt_y]==0){//当该点为0且未曾经过时,递归
dfs(nxt_x,nxt_y);
}
}
}
代码2(最小步数)
#include<iostream>
using namespace std;
int a[100][100];//迷宫
int vis[100][100];//访问
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n;//规格n*n
int stepmin=100000;//设置步数最小值
void dfs(int x,int y,int step){
if(x==n&&y==n){//如果到达目的地,更新步数最小值
if(step<stepmin){
stepmin=step;
}
return;
}
for(int i=0;i<4;i++){//向四周找是否有路可走
int nxt_x=x+dx[i];
int nxt_y=y+dy[i];
if(nxt_x<1||nxt_y<1||nxt_x>n||nxt_y>n){//超过n*n边界,不进行递归
continue;
}
if(a[nxt_x][nxt_y]==0&&vis[nxt_x][nxt_y]==0){//当该点为0且未曾经过时,递归
vis[nxt_x][nxt_y]=1;
dfs(nxt_x,nxt_y,step+1);
vis[nxt_x][nxt_y]=0;
}
}
return;
}
int main(){
while(~scanf("%d",&n)){
int startx,starty;
scanf("%d%d",&startx,&starty);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
vis[startx][starty]=1;
dfs(startx,starty,0);
printf("%d\n",stepmin);
}
return 0;
}
代码3(写出所有路径)
#include<bits/stdc++.h>
using namespace std;
int mp[100][100];
int m,n;
int startx,starty,endx,endy;
int vis[100][100];
bool flag;
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
struct node{
int x,y;
};
vector<node> v;
void dfs(int x,int y){
if(x==endx&&y==endy){
for(int i=0;i<(int)v.size();i++){
cout<<"("<<v[i].x<<","<<v[i].y<<")->";
}
cout<<"("<<endx<<","<<endy<<")"<<endl;
flag=true;
return;
}
vis[x][y]=1;
v.push_back({x,y});
for(int i=0;i<4;i++){
int nxt_x=x+dx[i];
int nxt_y=y+dy[i];
if(nxt_x<1||nxt_y<1||nxt_x>m||nxt_y>n){
continue;
}
if(!vis[nxt_x][nxt_y]&&mp[nxt_x][nxt_y]==1){
dfs(nxt_x,nxt_y);
}
}
vis[x][y]=0;
v.pop_back();
}
int main(){
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
scanf("%d",&mp[i][j]);
}
}
scanf("%d%d%d%d",&startx,&starty,&endx,&endy);
dfs(startx,starty);
if(!flag){
cout<<"-1"<<endl;
}
return 0;
}
代码4(写出第一个最短路径)
#include<bits/stdc++.h>
using namespace std;
int mp[100][100];
int m,n,stepmin=100000;
int startx,starty,endx,endy;
int vis[100][100];
bool flag;
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
struct node{
int x,y;
};
vector<node> pv;
vector<node> minv;
void dfs(int x,int y,int step){
if(x==endx&&y==endy){
if(step<stepmin){
stepmin=step;
minv.clear();
for(int i=0;i<(int)pv.size();i++){
minv.push_back({pv[i].x,pv[i].y});
}
flag=true;
return;
}
}
vis[x][y]=1;
pv.push_back({x,y});
for(int i=0;i<4;i++){
int nxt_x=x+dx[i];
int nxt_y=y+dy[i];
if(nxt_x<1||nxt_y<1||nxt_x>m||nxt_y>n){
continue;
}
if(!vis[nxt_x][nxt_y]&&mp[nxt_x][nxt_y]==1){
dfs(nxt_x,nxt_y,step+1);
}
}
vis[x][y]=0;
pv.pop_back();
}
int main(){
scanf("%d%d",&m,&n);
flag=false;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
scanf("%d",&mp[i][j]);
}
}
scanf("%d%d%d%d",&startx,&starty,&endx,&endy);
dfs(startx,starty,0);
if(!flag){
cout<<"-1"<<endl;
}
else{
for(int i=0;i<(int)minv.size();i++){
cout<<"("<<minv[i].x<<","<<minv[i].y<<")->";
}
cout<<"("<<endx<<","<<endy<<")"<<endl;
}
return 0;
}
八皇后
题目
代码
#include <iostream>
using namespace std;
int n,num;
int a[100],col[100],dg[100],udg[100];
void dfs(int row){
if(row==n+1){
num++;
if(num<=3){
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<"\n";
}
return;
}
for(int i=1;i<=n;i++)
if(col[i]==0&&dg[row+i]==0&&udg[row-i+n]==0){
a[row]=i;
col[i]=dg[row+i]=udg[row-i+n]=1;
dfs(row + 1);
col[i]=dg[row+i]=udg[row-i+n]=0;
a[row]=0;
}
}
int main(){
cin>>n;
dfs(1);
cout<<num;
return 0;
}