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

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

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

    因为深搜题我已经刷了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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值