您的位置:首页 > 其它

DFS专题(入门,经典为主)

2018-01-15 16:54 155 查看
    接触了图论以后,我才发现搜索原来是那么的简单。由于最近刘老师给我们讲的图论题实在是不太能够消化,于是我就转向了搜索那一块,从此与搜索过上了幸福美好的生活。

    最近突然才发现,搜索其实还是挺简单的。以前培训的时候,最害怕的就是搜索了,感觉完全听不懂。然而,现在随便翻一下黑皮书就明白了,我也不知道究竟是为什么。学会搜索后,就又有了一大波水题哈哈哈。

    因为深搜题我已经刷了2个大周了,便觉得特别亲切,就先讲几道深搜题吧!

                                                                             华丽丽的分割线                                                                                 

    第一题:细胞问题

    这是一道非常典型的题,在一个二维数组中进行深度优先搜索,开一个方向数组,想上下左右四个方向进行搜索。

#include<bits/stdc++.h>
using namespace std;

int n,k,m,ans=0;
char a[200][200];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组

inline void into() //输入

{
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) cin>>a[i][j];
}

void dfs(int x,int y) //深搜
{
for(int i=0;i<4;i++) //朝四个方向进行搜索
{
int xx=x+dx[i],yy=y+dy[i];
if(a[xx][yy]!='0')
{
a[xx][yy]='0';
dfs(xx,yy);
}
}
}

int main()
{
memset(a,'0',sizeof(a));
into();
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if (a[i][j]!='0')
{
ans++;
a[i][j]='0';
dfs(i,j);
}
cout<<ans;
return 0;
}  第二题:迷宫
这道题也算是非常典型了,与上一道题差不多,只是多加了一个回溯罢了。不多说了,代码如下:

#include<bits/stdc++.h>
using namespace std;

int n,m,t,sx,sy,fx,fy,x,y,ans=0;
bool a[100][100];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组,仍然是上下左右四个方向

void dfs(int x,int y) //深搜
{
if (x==fx&&y==fy) //如果到达终点,方案数加一,跳出
{
ans++;
return;
}
a[x][y]=false; //这样就能够不让往回走
for(int i=0;i<4;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if (a[xx][yy]==true) dfs(xx,yy);
}
a[x][y]=true; //回溯
}

int main()
{
memset(a,false,sizeof(a)); //边界先为假
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) a[i][j]=true;
for (int i=1;i<=t;i++) //不能走的地方也置为假
{
cin>>x>>y;
a[x][y]=false;
}
dfs(sx,sy);
cout<<ans;
return 0;
}

  刷完了两道经典题,感觉信心满满,下面就来一道更经典的题吧,这是我曾经的噩梦,就来详细的说一下吧。
  八皇后:

  相信这一道题大家肯定都不陌生,至少对于学过搜索,接触过搜索的同学们,这是一道必刷的题。这道题教上面,稍微难了一点,不过还是花了我10分钟左右。

  题目描述:(无)大致就是在n*n的棋盘内放置皇后,使他们不能再同一行,同一列,同一斜排。代码如下:

  #include<bits/stdc++.h>
using namespace std;

int n,k,s=0;
bool a[300]={},b[1000]={},c[1000]={}; //a是竖排的,b和c分别是斜排的

void dfs(int k) //深搜
{
if(k-1==n) //如果放满了,方案数加一,跳出
{
s++;
return;
}
for(int i=1;i<=n;i++) //放n个皇后
{
if(a[i]==false&&b[i-k+100]==false&&c[i+k]==false) //分别判断竖排和斜排是否会造成攻击,不加100会变负数
{
a[i]=true;
b[i-k+100]=true;
c[i+k]=true;
dfs(k+1);
a[i]=false; //一大堆回溯
b[i-k+100]=false;
c[i+k]=false;
}
}
}

int main()
{
cin>>n;
dfs(1);
cout<<s;
return 0;
}   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~又一道华丽丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 写完了题解,感觉特别开心,果然有代码博客写的就是快哈哈哈哈。那么就告一段落了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: