Loading

abc 246 e 题解

abc 246 e

AT 链接

洛谷链接

题意

有一个 \(N \times N\) 的棋盘,\((i, j)\) 表示棋盘第 \(i\) 行第 \(j\) 列的格子,行编号和列编号都是 \(1, 2, \dots, N\)

棋盘用 \(N\) 个长度为 \(N\) 的字符串 \(S_i\) 描述:

  • 如果 $S_{i, j} = $ .,则格子 \((i, j)\) 是空的。

  • 否则,格子 \((i, j)\) 有障碍。

一开始格子 \((A_x, A_y)\) 放了一颗棋子。在每次移动中,棋子可以朝某个对角线(某个斜 45 度方向)行走若干步后停下。棋子不能走出棋盘范围,并且该次移动的路径中不能包含障碍格子。

请你求出棋子从 \((A_x, A_y)\) 走到 \((B_x, B_y)\) 所需的最少移动次数。如果无法移动到 \((B_x, B_y)\),输出 -1

\(2 \le N \le 1500\)

\(1 \le A_x, A_y, B_x, B_y \le N\)

\((A_x, A_y) \ne (B_x, B_y)\)

思路

很明显,这题求最短路,是广搜。

但是,这个移动方式很让人头疼,每次到底挪动几次呢?

如果每次都去枚举移动的步数,时间复杂度又变成了 \(O(n ^ 3)\),会超时。

那么,我们应该怎么解决呢?

其实,每次只用走一步,但是,我们每次需要记录是往哪个方向走的。

如果当前走的方向和转移来的那个状态的转移方向是不同的,就需要多一次操作,否则,就还是这次操作。

因为每次转移有可能增加操作次数,有可能不增加,所以是 0-1 BFS,用双端队列维护。

#include <bits/stdc++.h>

using namespace std;

const int N = 1510;

const int dx[] = {1, 1, -1, -1};
const int dy[] = {1, -1, 1, -1};

int n, sx, sy, fx, fy, d[N][N][4];
char c[N][N];

struct Node {
  int x, y, dir;  // dir 表示方向
};

deque<Node> que;

void Record(int x, int y, int dis, int dir, int nowd) {
  if (x < 1 || x > n || y < 1 || y > n || c[x][y] == '#' || d[x][y][nowd] <= dis + (nowd != dir)) {
    return ;
  }
  d[x][y][nowd] = dis;
  if (nowd == dir) {
    que.push_front({x, y, nowd});
  } else {
    d[x][y][nowd]++;
    que.push_back({x, y, nowd});
  }
}

void bfs() {
  for (Record(sx, sy, 0, 4, 4); !que.empty(); ) {
    Node u = que.front();
    que.pop_front();
    for (int i = 0; i < 4; i++) {  // 转移
      Record(u.x + dx[i], u.y + dy[i], d[u.x][u.y][u.dir], u.dir, i);
    }
  }
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> sx >> sy >> fx >> fy;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      cin >> c[i][j];
      d[i][j][0] = d[i][j][1] = d[i][j][2] = d[i][j][3] = 1e9;  // 初始化
    }
  }
  bfs();
  int ans = 1e9;
  for (int i = 0; i < 4; i++) {
    if (d[fx][fy][i] != 1e9) {
      ans = min(ans, d[fx][fy][i]);
    }
  }
  cout << (ans == 1e9 ? -1 : ans);
  return 0;
}
posted @ 2024-09-20 17:10  chengning0909  阅读(5)  评论(0编辑  收藏  举报