DFS的联通性问题
  • DFS就像是一支轻骑兵冲向敌阵,然后后续部队从轻骑兵开辟的道路继续向敌阵如轻骑兵一样地冲锋陷阵,而BFS就像是铁锁链连起来的船队,一艘船的移动带动另一艘船的移动。

模板

bool dfs(起点,终点,其他信息)
{
	if( 到达 )
	   return true;
	   
	used[st.first][st.second] = true;
    fir(i,0,4)
	{
        int nx = st.first + dx[i] , ny = st.second + dy[i];
        if( nx < 0 || ny < 0 || nx >= n || ny >= n)//越界
            continue;
        if( used[nx][ny] == true )//使用过
            continue;
        if( mapp[nx][ny] == '#' )//障碍物
            continue;
        
        if(dfs( 起点,终点,其他信息)) 
            return true;
	}

	return false;
}
  • 凡是遇到越界、已被使用和障碍的条件,一律continue到下一种情况
  • 关于中间层的一个dfs返回值为false的思考。
    • 这个中间层的dfs作为上一层四个dfs之一,只是不让其返回true,并不代表会返回false(当然如果四个都返回false,上一层就会继续返回false),且最终的false的返回值只跟第一次进入时的返回值有关。

例题

1.AcWing 1112. 迷宫

#include<bits/stdc++.h>
#define fir(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef pair<int , int> PII;
const int N = 1e2+10;
char mapp[N][N];
bool used[N][N];	
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};

bool dfs(PII st,PII end,int n)
{
	if( st.first == end.first && st.second == end.second)
	   return true;
	   
	used[st.first][st.second] = true;
    fir(i,0,4)
	{
        int nx = st.first + dx[i] , ny = st.second + dy[i];
        if( nx < 0 || ny < 0 || nx >= n || ny >= n)
            continue;
        if( used[nx][ny] == true )
            continue;
        if( mapp[nx][ny] == '#' )
            continue;
        
        if(dfs( make_pair(nx,ny) ,end,n))
            return true;
	}

	return false;
}

void init()
{
	memset(used,false,sizeof(used));
}

int main()
{
	int k;
	cin>>k;
	while(k--)
	{
		init();
		
		int n;
		cin>>n;
		fir(i,0,n)
		    fir(j,0,n)
		       cin>>mapp[i][j];
	
	    int x1,y1,x2,y2;
	    cin>>x1>>y1>>x2>>y2;
	    PII st(x1,y1),end(x2,y2);
	    if( mapp[x1][y1]!='#' && mapp[x2][y2]!='#' && dfs(st,end,n))
	       cout<<"YES"<<endl;
	    else cout<<"NO"<<endl;
	}
	return 0;
}

2.AcWing 1113. 红与黑

#include<bits/stdc++.h>
#define fir(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef pair <int,int > PII;
const int N = 2e1+5;
bool used[N][N];
char mapp[N][N];
int dx[] = {0,0,-1,1};
int dy[] = {-1,1,0,0};

int n,m;
int cnt=0;
void dfs(PII st)
{
	used[st.first][st.second]=true;//好马不吃回头草 
    cnt++;
	fir(i,0,4) 
	{
	    int nx = st.first + dx[i];
		int ny = st.second + dy[i];
		if( nx<1 || ny<1 || nx>m || ny>n )
		   continue;
		if( mapp[nx][ny] == '#' )
		   continue;
		if( used[nx][ny] == true)
		   continue;
		dfs(make_pair(nx,ny));	
    }	
}

void init()
{
	cnt = 0;
	memset(used,false,sizeof(used));
}

int main()
{
	while(1)
	{
	    cin>>n>>m;
	    init();
	    if( n== 0 && m== 0)break;
	    PII st;
	    fir(i,1,m+1)//刚开始用宏来表示循环,右边界是开的状态,这里要加上1 
	       fir(j,1,n+1)
	        {
	   	        cin>>mapp[i][j];
	   	        if(mapp[i][j]=='@')
	   	            st = make_pair(i,j);
            }	   	   
	    dfs(st);
	    cout<<cnt<<endl;   
    }
	return 0;
}
其他

pair

DFS的联通性问题_#include