dfs bfs

来源:互联网 发布:王家卫表白方式 知乎 编辑:程序博客网 时间:2024/06/05 23:00

dfs

深度优先搜索是搜索的手段之一。他是从某个状态开始,不断地转移状态,直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直到找到最终的解。

深刻运用了递归的思想。隐式地利用了栈进行计算。

经典例题    POJ 2386

有一个大小为N×M的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少水洼?

// 输入int N, M;char field[MAX_N][MAX_M + 1]; // 园子// 现在位置(x,y)void dfs(int x, int y) {  // 将现在所在位置替换为.  field[x][y] = '.';  // 循环遍历移动的8个方向  for (int dx = -1; dx <= 1; dx++) {    for (int dy = -1; dy <= 1; dy++) {      // 向x方向移动dx,向y方向移动dy,移动的结果为(nx,ny)      int nx = x + dx, ny = y + dy;     // 判断(nx,ny)是不是在园子内,以及是否有积水      if (0 <= nx && nx < N && 0 <= ny && ny < M && field[nx][ny] == 'W') dfs(nx, ny);    }  }  return ;}void solve() {  int res = 0;  for (int i = 0; i < N; i++) {    for (int j = 0; j < M; j++) {      if (field[i][j] == 'W') {        // 从有W的地方开始dfs        dfs(i, j);        res++;      }    }  }  printf("%d\n", res);}

bfs

宽度优先搜索也是搜索的手段之一。他与深度优先搜索类似,从某个状态出发探索所有可以到达的状态。

与深度优先搜索不同之处在于搜索的顺序,宽度优先搜索总是先搜索距离初始状态近的状态。也就是说,它是按照开始状态—>只需一次就能到达的所有状态—>只需两次就能到达的所有状态—>……这样的顺序进行搜索。对于同一个状态,宽度优先搜索只经过一次,因此复杂度为O(状态数*转移的方式)。利用了队列。

经典例题     迷宫的最短路径

给定一个大小为N*M的迷宫,由通道('.')和墙壁('#')组成,其中通道S表示起点,通道G表示终点,每一步移动可以达到上下左右中不是墙壁的位置。试求出起点到终点的最小步数。(本题假定迷宫是有解的)(N,M<=100)

#include <iostream>  #include <queue>  using namespace std;  const int MAX_N = 100;  const int MAX_M = 100;  const int INF = 0x3f3f3f3f;  typedef pair<int, int> P;  char maze[MAX_N][MAX_M + 1];  int N, M;  int sx, sy; //起点的位置  int gx, gy; //终点的位置    int d[MAX_N][MAX_M];//储存起点到某一点的距离  int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 }; //表明每次x和y方向的位移    void bfs()  {      queue<P> que;      for (int i = 0; i < N; i++)          for (int j = 0; j < M; j++)              d[i][j] = INF;  //初始化所有点的距离为INF      que.push(P(sx, sy));      d[sx][sy] = 0;  //从起点出发将距离设为0,并放入队列首端        while (que.size()) //题目保证有路到终点,所以不用担心死循环      {          P p = que.front(); que.pop();//弹出队首元素          int i;          for (i = 0; i < 4; i++)          {              int nx = p.first + dx[i];              int ny = p.second + dy[i];//移动后的坐标              //判断可移动且没到过              if (0 <= nx&&nx < N                  && 0 <= ny&&ny < M                  &&maze[nx][ny] != '#'                  &&d[nx][ny] == INF)//之前到过的话不用考虑,因为距离在队列中递增,肯定不会获得更好的解              {                  que.push(P(nx, ny));    //可以移动则设定距离为之前加一,放入队列                  d[nx][ny] = d[p.first][p.second] + 1;                  if(nx==gx && ny==gy) break;                            }          }          if(i!=4) break;      }    }    int main()  {      cin>>N>>M;      for (int i = 0; i < N; i++)          cin>>maze[i];      for (int i = 0; i < N; i++)          for (int j = 0; j < M; j++)          {              if (maze[i][j] == 'S')              {                  sx = i; sy = j;              }              if (maze[i][j] == 'G')              {                  gx = i; gy = j;              }          }      bfs();      cout<<d[gx][gy]<<endl;        return 0;  }  


0 0