zoukankan      html  css  js  c++  java
  • P1443 马的遍历

    一道队列广搜题

    此题使用队列实现,现将初始状态加入到空的队列当中;然后每次取出对首,找出队首所能转移到的状态,再将其压入队列;如此反复,这样就能保证一个状态在被访问的时候一定是采用的最短路径。

    广度优先搜索的一般形式

    这里是使用队列实现广度优先搜索的一般形式:

    Q.push(初始状态);//将初始状态入队
    while (!Q.empty()) {
      State u = Q.front();//取出对首
      Q.pop();//出队
      for (枚举所有可扩展状态) //找到u的所有可达状态v
        if (是合法的)  //v需要满足某些条件,如未访问过、未在队内等
          Q.push(v);//入队(同时可能需要维护某些必要信息)
    }
    

    就本题而言,先建立一个结构体数组用于存储扩展的节点。先让起点入队,然后在队列取状态逐个扩展。容易被证明每个点被扩展到时一定是最小步数。复杂度是O(mn)

    代码实现

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #define maxn 310
    
    using namespace std;
    
    struct Node {
      int x, y;
    };
    
    queue<Node> Q;
    int ans[maxn][maxn];
    int walk[8][2] = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}, };
    
    int main() {
      int n, m, sx, sy;
      memset(ans, -1, sizeof(ans));
      scanf("%d %d %d %d", &n, &m, &sx, &sy);
      Node tmp = {sx, sy};
      Q.push(tmp);
      ans[sx][sy] = 0;
      while(!Q.empty()) {
        Node u = Q.front();
        int ux = u.x, uy = u.y;
        Q.pop();
        for (int k = 0; k < 8; ++k) {
          int x = ux + walk[k][0];
          int y = uy + walk[k][1];
          int d = ans[ux][uy];
          if (x < 1 || x > n || y < 1 || y > m || ans[x][y] != -1) continue;
          ans[x][y] = d + 1;
          Node tmp = {x, y};
          Q.push(tmp);
        }
      }  
      for (int i = 1; i <= n; ++i, puts("")) {
        for (int j = 1; j <= m; ++j)
        printf("%-5d", ans[i][j]);
      }
      return 0;
    }
    
  • 相关阅读:
    最受欢迎的北大通选课导读·1[精品]
    社会保险,
    养老金的计算,
    毫秒 后的一个计算,
    返回格式 的数据结构再次改造,
    阶段状态池子,
    生活,-摘
    融合,
    tableview 也可以实现这个效果,
    字体大小 一致起来,
  • 原文地址:https://www.cnblogs.com/Kyriech-Francis/p/Answer_P1143.html
Copyright © 2011-2022 走看看