深度优先搜索算法(DFS)

1. 深度优先搜索属于图的遍历算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。

2.搜索策略:

深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;

直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,

重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

3.搜索伪代码:

DFS(Node)
{
	if(Node==目标节点)
		then//找到目标,return
	for each-next∈d[Node]
		doDFS(next);
	end
}

当然一般情况下的DFS算法的实现会用到数据结构-栈,也可以使用递归来实现,但是效率额偏低,所以要注意剪枝(就是提前排除不可能的情况)。

4.具体题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1016 质数环

//简单的DFS 不用剪枝,也可以A
//Time:890MS
//Mem :376K
#include <iostream>
#include <cstring>

using namespace std;

int ring[25];
int visited[25];
int n;

int isPrime(int p)
{
    if(p==1 || p==2 || p==3 || p==5 || p==7 || p==11 || p==13 || p==17 || p==19
        || p==23 || p==29 || p==31 ||p==37 || p==41 || p == 43)
        return 1;
    else
        return 0;
}

void dfs(int dep)
{
    if(dep == n)//跳出递归的条件。
    {
        if( isPrime(ring[n-1] + 1) )
        {
            for(int i=0; i<n-1; i++)
                cout<<ring[i]<<" ";
            cout<<ring[n-1]<<endl;
            return;
        }
    }

    for(int i=2; i<=n; i++)
    {
        if(!visited[i] && isPrime(ring[dep-1]+i) )
        {
            visited[i] = 1;
            ring[dep] = i;
            dfs(dep+1);
            visited[i] = 0;
        }
    }
    return;
}

int main()
{
    int test=0;
    while(cin>>n)
    {
        memset(ring, 0, sizeof(ring));
        memset(visited, 0, sizeof(visited));
        visited[1] = 1;
        ring[0] = 1;
        cout<<"Case "<<++test<<":\n";
        dfs(1);
        cout<<endl;
        
    }
    return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=1010 走迷宫(典型的DFS)

/*
	这个题目的剪枝思路如下:
	可以把迷宫看成这样: 
	0 1 0 1 0 1 
	1 0 1 0 1 0 
	0 1 0 1 0 1 
	1 0 1 0 1 0 
	0 1 0 1 0 1 
	从为 0 的格子走一步,必然走向为 1 的格子 
	从为 1 的格子走一步,必然走向为 0 的格子 
	即: 
 	0->1或1->0 必然是奇数步 
 	0->0 走1->1 必然是偶数步 
	所以:所以当遇到从 0 走向 0 但是要求时间是奇数的,或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达!
*/
	
//Time:62MS
//Mem :364K
#include <iostream> 
#include <string.h> 
#include <stdlib.h> 

using namespace std;

char map[9][9]; 
int n,m,t,di,dj; 
bool escape; 
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; //表示四个方向。
void dfs(int si,int sj,int cnt) 
{    
    int i,temp; 
    if(si>n || sj>m || si<=0 || sj<=0) 
        return; 
    if(cnt==t && si==di && sj==dj)    
        escape=1;
    if(escape) 
        return; 
  
   temp = (t-cnt) - abs(si-di) - abs(sj-dj); //奇偶剪枝
   if(temp<0 || temp&1)//如果为奇数。 
       return; 
   for(i=0;i<4;i++)
   { 
      if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
      { 
         map[si+dir[i][0]][sj+dir[i][1]]='X'; 
         dfs(si+dir[i][0],sj+dir[i][1],cnt+1); //使用递归实现栈。
         map[si+dir[i][0]][sj+dir[i][1]]='.'; 
      } 
   } 
   return; 
} 

int main() 
{ 
    int i,j,si,sj; 
    while(cin>>n>>m>>t)
    { 
      if(n==0 && m==0 && t==0) 
          break; 
      int wall=0;
      for(i=1; i<=n; i++) //i=0j=0的情况为墙。
         for(j=1; j<=m; j++)
         { 
            cin>>map[i][j]; 
            if(map[i][j]=='S') { si=i; sj=j; } //开始地
            else if(map[i][j]=='D') { di=i; dj=j; } //目的地
            else if(map[i][j]=='X') wall++; //墙的数目
         } 
       if(n*m-wall<=t)// n*m - t包括s和d节点。
       {
           cout<<"NO"<<endl;
           continue;
       }
       escape=0; 
       map[si][sj]='X';
       dfs(si,sj,0); 
       if(escape) 
           cout<<"YES"<<endl; 
       else 
           cout<<"NO"<<endl; 
   } 
   return 0; 
} 



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值