深度优先搜素及题目

一.深度优先搜索

1. 搜索是指已知初始状态和目标状态,对问题的中间状态进行枚举的遍历的一种算法,通俗的讲,搜索就是比较复杂的枚举。
2.深度优先搜索是按照深度的方式进行搜索,就是把所有可行的方案都列举出来,不断的去尝试,直到找到问题的解。
设想你在一个迷宫里面,当我们在起点时,总要通过各种岔路口才能找到迷宫的终点,那么从起点开始,沿着一条路向前走,当碰到岔路口时,选择其中一个岔路前进。如果选择的这个岔路前方是一条死路,那么就退回这个岔路口,选择另一个岔路前进。如果岔路口存在新的岔路口,那么就按上述方法再次执行,这样的话,我们便可以找到终点。

也就是说,当碰到岔路口时,总是以“深度”作为前进的关键,不碰到死胡同就不回头
那么,碰到死胡同后返回上个岔路口的这种方法称之为——回溯法

二.深度优先搜索之——回溯法。

1.回溯法是指从问题的某一角度出发,搜索所有的可能的情况,然后以其中的一种为新的出发点,继续向下探索,这样就走出了一条“路”,当这条路走到尽头时,返回上个出发点,从另外一种情况出发,继续搜索。及通过不断的“回溯”来寻找目标。

例:

数字的全排列:即123的全排列是123,132,213,231,312,321。即用1,2,3这三种数字组成一个3位数,且不允许出现重复的数字。

在这里插入图片描述
即如图所示,我们人为规定,1,2,3的选择方法是先选择1,再选2,最后选3。那么我们如果要进行全排列,便如图所示。
我们规定放第一个数字的是第一个盒子…以此类推,将数字放入盒子的代码:

void  dfs(int step)   
{
  for(i=1;i<=n;i++)   //一共有n个数字,在这里,n=3
  {
    if(book[i]==0)    //等于0表示这个数字还未被放入盒子中
    {
      a[step]=i;      //将数字i放在第step个盒子
      book[i]=1;
      dfs(step+1);      //放下一个数字
      book[i]=0;
     }
  }
  return;
}

那么结束的标准是什么呢,即当我们处理到第n+1个小盒子时,说明前面的n个盒子已经放好了,那么我们变将这种情况输出。即:

if(step==n+1)
 {
  for(i=1;i<=n;i++)
     printf("%d ",a[i]);
  printf("\n");
  return;
  }

完整代码如下:

#include<stdio.h>
int a[10],book[10],n;

void dfs(int step)
{
     int i;
     if(step==n+1)
     {
     	for(i=1;i<=n;i++)  //将这种情况打印出来
     	    printf("%d ",a[i]);
     	printf("\n");
     	return;
     }

   for(i=1,i<=n;i++)
   {
      if(book[i]==0)
      {
         a[step]=i;
         book[i]=1;
         dfs(step+1);
         book[i]=0;
      }
   }
   return;
}

int main()
{
   scanf("%d",&n);
   dfs(1);
   return 0;
  }

三.深搜的例题,走迷宫。

即我们用一个二维数组来储存这个迷宫,迷宫为n*m的大小,终点的坐标为(p,q),寻找从起点到终点的最短路径,我们规定顺序为向右走,向下,向左,向上。储存迷宫的二维数组中0代表可以走的路,1代表障碍物。
代码如下:

#include<stdio.h>
int n,m,p,q,min=1000000;
int a[20][20],book[20][20];
void dfs(int x,int y,int step)        //x,y为当前点的横纵坐标,step表示已经走过的步数。
{
  int next[4][2]={{0,1),{1,0},{0,-1},{-1,0}};          //分别为向右走,向下,向左,向上
  int tx,ty,k;         //tx,ty为下一个点的横纵坐标
  if(x==p&&y==q)       //判断是否到达终点
  {
     if(step<min)
     	min=step;
     return;
   }

  for(k=0;k<=3;k++)
  {
     tx=x+next[k][0];
     ty=y+next[k][1];
     if(tx<1||tx>n||ty<1||ty>m)
        continue;
     if(a[tx][ty]==0&&book[tx][ty]==0)
     {
        book[tx][ty]=1;
        dfs(tx,ty,step+1);
        book[tx][ty]=0;
     }
  }
  return;
  }

int main()
{
 int i,j,x,y;
 scanf("%d %d",&n,&m);   
 for(i=1;i<=n;i++)
   for(j=1;j<=m;j++)
     scanf("%d",&a[i][j]);       //读入迷宫
 scanf("%d %d %d %d",&x,&y,&p,&q);   //读入起点和终点
 book[x][y]=1;    //标记起点已经走过了,防止重复走
 dfs(x,y,0);
 printf("%d ",min);
 return 0;
}
发布了10 篇原创文章 · 获赞 2 · 访问量 217

猜你喜欢

转载自blog.csdn.net/dfwef24t5/article/details/104140246