[每日一题] [NC23486] 小A与小B

题目大意:一个迷宫里面有src和dst,src每次可以八个方向走一步,dst每次可以走两次,每次只能四个方向,不能走障碍物上。问最少多少次可以相遇。注意可以原地不动。

https://ac.nowcoder.com/acm/problem/23486

这题比较标准的双向BFS,注意可以原地不动。比如考虑这个case:

A #
# B

应该要输出1,而不是NO

#define MAXN 2000
int N,M;
char grid[MAXN][MAXN];

VPII src_dirs={
  {-1,-1},
  {-1,0},
  {-1,1},
  {0,-1},
  {0,1},
  {1,-1},
  {1,0},
  {1,1},
};
int src_dist[MAXN][MAXN];
int dst_dist[MAXN][MAXN];

int doit() {
  PII src={-1,-1}, dst={-1,-1};
  REP(i,N){
    REP(j,M){
      if(grid[i][j]=='C'){
        src={i,j};
        src_dist[i][j]=1;
      }
      if(grid[i][j]=='D'){
        dst={i,j};
        dst_dist[i][j]=1;
      }
    }
  }
  VPII src_layer;
  VPII dst_layer;
  src_layer.PB(src);
  dst_layer.PB(dst);
  int l = 0;
  while (!src_layer.empty() || !dst_layer.empty()) {
    ++l;
    VPII tmp_src, tmp_dst;
    for (PII x : src_layer) {
      for (PII dir : src_dirs) {
        PII n = {x.FI+dir.FI,x.SE+dir.SE};
        if(n.FI<0||n.FI>=N)continue;
        if(n.SE<0||n.SE>=M)continue;
        if(grid[n.FI][n.SE]=='#')continue;
        if(src_dist[n.FI][n.SE]){
          continue;
        }
        src_dist[n.FI][n.SE]=1;
        if (dst_dist[n.FI][n.SE]){
          return l;
        }
        tmp_src.PB(n);
      }
    }
    for (PII x : dst_layer) {
      for (PII dir : dirs) {
        PII n = {x.FI+dir.FI,x.SE+dir.SE};
        if (n.FI < 0 || n.FI >= N) continue;
        if (n.SE < 0 || n.SE >= M) continue;
        if (grid[n.FI][n.SE] == '#') continue;
        if (dst_dist[n.FI][n.SE]) {
          continue;
        }
        dst_dist[n.FI][n.SE] = 1;
        if (src_dist[n.FI][n.SE]) {
          return l;
        }
        tmp_dst.PB(n);
      }
    }
    dst_layer=tmp_dst;
    CLR(tmp_dst);
    for (PII x : dst_layer) {
      for (PII dir : dirs) {
        PII n = {x.FI+dir.FI,x.SE+dir.SE};
        if (n.FI < 0 || n.FI >= N) continue;
        if (n.SE < 0 || n.SE >= M) continue;
        if (grid[n.FI][n.SE] == '#') continue;
        if (dst_dist[n.FI][n.SE]) {
          continue;
        }
        dst_dist[n.FI][n.SE] = 1;
        if (src_dist[n.FI][n.SE]) {
          return l;
        }
        tmp_dst.PB(n);
      }
    }
    src_layer=tmp_src;
    dst_layer=tmp_dst;
  }
  return -1;
}

int main(int argc, char* argv[]) {
  read(N,M);
  REP(i,N){
    REP(j,M){
      scanf(" %c",&grid[i][j]);
    }
  }
  int ans = doit();
  if (ans < 0) {
    printf("NO\n");
  } else {
    printf("YES\n");
    printint(ans);
  }
  return 0;
}
全部评论

相关推荐

HR_丸山彩同学:你的项目描述里,系统设计讲了很多:MemCube是什么、三级存储架构怎么设计、四种遗忘策略分别是什么。这些面试的时候讲没问题,但简历上不需要这么细。 简历要突出的是影响力,不是实现细节。面试官看简历的时候想知道的是「这个项目有多大价值」,不是「这个项目具体怎么实现的」。实现细节是面试时候聊的 怎么改:技术细节可以精简为一句「采用三级存储架构+四种遗忘策略」,把省出来的篇幅用来写影响力。比如:项目有没有开源?有没有写成技术博客?有没有被别人使用过? 校园经历没有任何信息量,任何人都可以写这句话,写了等于没写。更关键的是,你投的是技术岗,校园活动经历本来就不是加分项。如果非要写,必须写出具体的数字和成果。如果你没有这些数字,那就老老实实删掉 「端到端耗时缩减30-40%」要给出确切数字和绝对值。从1000ms降到600ms是降了40%,从100ms降到60ms也是降了40%,但这两个含义完全不一样。其他也是,涉及到数据,准备好证据,口径统一,面试会问 「熟练」「熟悉」「了解」混在一起用,读起来很乱。而且「了解前端需求」最好改成「具备前后端协作经验」
点赞 评论 收藏
分享
浅白lw:其实是牛马自己换马了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务