概述
深度优先算法是一种很基本,常用的算法,是搜索算法中的一种。
它的实现主要用到了递归的思想,在一些树和图的遍历中,DFS会尽可能深地搜索树的分支,或搜索图的边,等到搜索条件不符合时,又回溯到上一节点,尝试其他走法。简单解释就是一条路走到黑,头很铁。在编程题目中一般用于解决迷宫类题目,棋盘类题目,如八皇后,跳马问题,连通问题,连通问题等。不过这种方法一般比较耗时,特别是在棋盘较大较复杂时,要较长时间才能算出结果,这时应该考虑广度优先(BFS)算法。
一般格式
void DFS(坐标,其他数据)
{
if(条件)
{
相关操作;
return;//边界等条件
}
if(条件)
{
相关操作(标记);
DFS(坐标,下一步)//递归
(回溯)
}
}
题目1:八皇后
比较典型的回溯法题目,注意回溯条件的设置
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using std::string;
int chessmap[8][8],cnt=0;
void print(int m[8][8])
{
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)
{
if(m[i][j])std::cout<<"Q ";
else std::cout<<"X ";
}
std::cout<<std::endl;
}
std::cout<<std::endl;
}
bool judge(int r,int c,int n)
{
for(int i=0;i<c;i++)
{
if(chessmap[r][i]==1)return false;
}
for(int i=0;i<r;i++)
{
if(chessmap[i][c]==1)return false;
}
for(int i=r-1,j=c-1;i>=0,j>=0;i--,j--)
{
if(i<0||j<0)break;
if(chessmap[i][j]==1)return false;
}
for(int i=r-1,j=c+1;i>=0,j<n;i--,j++)
{
if(i<0||j<0||j>=n)
break;
if(chessmap[i][j]==1)
return false;
}
return true;
}
void queens(int n,int row)
{
if(row==n)
{
print(chessmap);
cnt++;
/*memset(chessmap[row-1],0,sizeof(chessmap[row-1]));*/
}
else
{
for(int col=0;col<n;col++)
{
if(judge(row,col,n)==true)
{
chessmap[row][col]=1;
queens(n,row+1);
memset(chessmap[row],0,sizeof(chessmap[row]));
}
/* else
{
if(col==n-1)
{
memset(chessmap[row-1],0,sizeof(chessmap[row-1]));
}
}*/
}
}
}
int main()
{
memset(chessmap,0,sizeof(chessmap));
queens(8,0);
std::cout<<cnt;
return 0;
}
题目2:油田连通问题
用一个count来作标记,每多一个连通量count+1,最后输出count就行了。
比较无脑,照着格式套条件就行
#include<iostream>
#include<string.h>
#include<string>
using std::string;
const int maxn=100+5;
char oilmap[maxn][maxn];
int m,n,scan[maxn][maxn];
void DFS(int row,int col,int idx)
{
if(row<0||row>=m||col>=n||col<0)return;//judge edge
if(oilmap[row][col]!='@'||scan[row][col]>0)return;//judge if visited
scan[row][col]=idx;
for(int i=-1;i<=1;i++)
{
for(int j=-1;j<=1;j++)
{
if(i!=0||j!=0)DFS(row+i,col+j,idx);//recursion
}
}
}
int main()
{
int count=0;
std::cin>>m>>n;
memset(scan,0,sizeof(scan));//clear
for(int i=0;i<m;i++)
{
std::cin>>oilmap[i];
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(scan[i][j]==0&&oilmap[i][j]=='@')
DFS(i,j,++count);//recursion
}
}
std::cout<<count<<std::endl;
return 0;
}
今天跟高中同学玩去了,只做了一点题,比较佛,明天认真更新>_<