dfs(深度搜索法)
1.首先确定深度或搜索终点
2.利用函数递归(适当做回溯)
【缺点:难以找到最优解但占用内存小】
例题1:Oil Deposits
经典连通块问题
ac代码:
#include <cstdio>
#include <iostream>
#include <string.h>
using namespace std ;
char tian[101][101] ;
int id[101][101] ;
int n , m ;
void dfs ( int x , int y , int num )
{
if( x<0 || x>=n || y<0 || y>=m ) return;
if( tian[x][y] != '@' || id[x][y] != 0 ) return ; //确定边界
id[x][y] = num ;
for( int dx = -1 ; dx <= 1 ; dx++ ) //对八个方向进行搜索
for( int dy = -1 ; dy <= 1 ; dy++ )
{
if( dx != 0 || dy != 0 )
dfs( x+dx , y+dy , num ) ; //利用递归深入,用num记录已遍历
}
}
int main ()
{
while( ~scanf("%d%d" , &n , &m ) )
{
if( n==0 && m==0 ) break ;
int t = 0 ;
memset( id , 0 , sizeof(id) ) ;
for(int i=0 ; i<n ; i++ )
scanf("%s" , tian[i] ) ;
for( int i = 0 ; i<n ; i++ )
for( int j =0 ; j<m ; j++ )
{
if(tian[i][j] == '@' && id[i][j] == 0 )
{
t++ ;
dfs( i , j , t ) ;
}
}
printf("%d\n" , t ) ;
}
return 0 ;
}
例题2:八皇后
注意输出顺序,以及利用回溯法
#include <cstdio>
#include <iostream>
using namespace std ;
int pan[8][8]={0} , ed[10] ;
int n=8 , t=1 ;
bool lie( int z )
{
for( int i = 0 ; i < z ; i++ )
{
if( ed[z]==ed[i] || ed[z]-ed[i] == z - i || ed[i]-ed[z] == z-i )
return 0 ;
}
return 1 ;
} //检查相同列
void dfs( int x)
{
if( x >= 8 )
{
printf("No. %d\n" , t++ ) ;
for( int i = 0 ; i < n ; i++ )
{
for( int j = 0 ; j < n ; j++ )
printf("%d " , pan[j][i] ) ;
printf("\n") ;
}
}
for( int i = 0 ; i < n ; i++ )
{
ed[x] = i ;
if( pan[x][i] != 1 && lie(x) )
{
pan[x][i] = 1 ;
dfs( x+1 ) ;
pan[x][i] = 0 ; //利用回溯还原不成立情况
}
}
}
int main ()
{
dfs(0) ;
return 0 ;
}
最后总结:确定会使用基础dfs 但还需要多联系。