1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
// 非常类似于dijskra
#include <iostream>
#include <cstring>
#include <deque>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 550;
int n, m; // 方格的数量为n * m
char g[N][N]; // 存储每个方格内的数据
int dist[N][N]; // 到达每个格点需要的步数
bool st[N][N]; // 判重数组,判断该点是否已求出结果
int bfs() {
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[0][0] = 0;
deque<PII> q;
q.push_back({0, 0});
char cs[] = "\\/\\/"; // 与格点导通的四种情况
int dx[] = {-1, -1, 1, 1}, dy[] = {-1, 1, 1, -1}; // 相邻的四个格点
int ix[] = {-1, -1, 0, 0}, iy[] = {-1, 0, 0, -1}; // 与当前格点相邻的四个方格
while (q.size()) {
PII t = q.front(); q.pop_front();
if (st[t.x][t.y]) continue; // 当前点已经求出最短距离
st[t.x][t.y] = true;
for (int i = 0; i < 4; i++) {
int a = t.x + dx[i], b = t.y + dy[i];
if (a < 0 || a > n || b < 0 || b > m) continue;
int ca = t.x + ix[i], cb = t.y + iy[i]; // 考察与当前格点相邻的第i个方格
int w = (g[ca][cb] != cs[i]); // 不能导通,需要旋转一次
int d = dist[t.x][t.y] + w;
// 因为某个格点可能入队多次,需要更新dist[a][b],更新后的数据需要入队
if (d < dist[a][b]) {
dist[a][b] = d;
if (w) q.push_back({a, b});
else q.push_front({a, b});
}
}
}
return dist[n][m];
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) scanf("%s", g[i]);
if ((n + m) & 1) puts("NO SOLUTION");
else printf("%d\n", bfs());
}
return 0;
}
|