DFS(depth-first search)是一种搜索手段,它从某一个状态开始,不断转移,直到状态无法转移回退到前一步,继续转移到其他的状态,不断重复,知道找到它的解。根据这种性质,DFS用递归实现比较简单。
我们来看几道题来理解一下dfs.
第一道题就是求全排列
#include <iostream>
using namespace std;
int a[10],flag[10],n;
void dfs(int x){
if(x==n+1){ //求n个数字的全排列,当x超过n输出结果
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return; //输出之后返回上一个状态
}
for(int i=1;i<=n;i++){
if(flag[i]==0){
a[x]=i; //将数组赋值之后,把这个数字打上一个标记
flag[i]=1;
dfs(x+1); //调用到下一层函数
flag[i]=0; //取消标记
}
}
return; //返回到上一个状态
}
int main(){
cin>>n;
dfs(1);
return 0;
}
通过这个题,我们可以总结出一个DFS的基本模板
bool judge(/*参数*/){
if(/*判断条件*/){
return false;
}
return true;
}
void dfs(/*参数*/){
/*判断是否是边界*/
{
/*输出*/
}
return;
/*循环*/{
/*判断是否满足条件*/
/*标记*/
dfs(/*下一个状态*/)
/*去掉标记*/
}
}
第二道题,是洛谷里的点这里
输入样例:
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
输出样例:3
//从任意w开始,不停地把邻接的部分用'.'替换,换了几次就证明有几个水洼
#include <iostream>
using namespace std;
char a[101][101];
int n,m;
void dfs(int x,int y){
a[x][y]='.';
for(int dx=-1;dx<=1;dx++){
for(int dy=-1;dy<=1;dy++){
int nx=x+dx;
int ny=y+dy;
if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]=='W'){
dfs(nx,ny);
}
}
}
return;
}
int sum;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(a[i][j]=='W'){
dfs(i,j);
sum++;
}
}
}
cout<<sum;
}
最后一题,就是大名鼎鼎的八皇后问题点这里
其实我的代码是无法ac的,最后一个点会超时,还需要自己改进一下。
#include <iostream>
using namespace std;
int a[14][14];
int n,cnt;
bool pd(int x,int y,int n){ //判断皇后是否危险
for(int i=1;i<=n;i++){ //判断行
if(a[i][y]==1){
return false;
}
}
for(int i=x,j=y;i>=1&&j>=1;i--,j--){ //判断对角线
if(a[i][j]==1){
return false;
}
}
for(int i=x,j=y;i>=1&&j<=n;i--,j++){ //判断另一条对角线
if(a[i][j]==1){
return false;
}
}
return true;
}
void dfs(int x){
if(x==n+1){
if(cnt<3){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]==1){
if(i==n){
cout<<j;
}else{
cout<<j<<" ";
}
}
}
}
cout<<endl;
}
cnt++;
return;
}
for(int j=1;j<=n;j++){
if(pd(x,j,n)){
a[x][j]=1;
dfs(x+1);
a[x][j]=0;
}
}
}
int main(){
cin>>n;
dfs(1);
cout<<cnt;
return 0;
}
主要参考的是《挑战程序设计竞赛》
和一些大佬的文章点这里,大佬写的比我好很多。我的csdn可能记录的意义大于其他的意义啦。