#include #include #define MAXN 550 #define QSIZE (3 * 500 * 500) enum posture { pos_s, pos_h, pos_v }; struct q_node { int row; int col; posture pos; }; int T; int n, m; int dist_s[MAXN][MAXN], dist_h[MAXN][MAXN], dist_v[MAXN][MAXN]; q_node q[QSIZE]; int q_head = 0; int q_tail = 0; void q_clear() { q_head = 0; q_tail = 0; } bool q_empty() { return q_head == q_tail; } void enq(q_node node) { q[q_tail] = node; q_tail++; q_tail %= QSIZE; } q_node deq() { q_node ret = q[q_head]; q_head++; q_head %= QSIZE; return ret; } int start_row, start_col; posture start_pos; int end_row, end_col; int map[MAXN][MAXN] = {0}; // 0 = wall // 1 = ground // 2 = glass bool valid_pos(int row, int col, posture pos) { if (row >= n || col >= m || row < 0 || col < 0) { return false; } if (pos == pos_s) { return map[row][col] == 1; } else if (pos == pos_h) { if (col + 1 >= m) return false; return map[row][col] > 0 && map[row][col + 1] > 0; } else if (pos == pos_v) { if (row + 1 >= n) return false; return map[row][col] > 0 && map[row + 1][col] > 0; } else { // should not be here return false; } } int bfs() { // init q_clear(); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { dist_s[i][j] = -1; dist_h[i][j] = -1; dist_v[i][j] = -1; } } if (start_pos == pos_s) { dist_s[start_row][start_col] = 0; } else if (start_pos == pos_h) { dist_h[start_row][start_col] = 0; } else if (start_pos == pos_v) { dist_v[start_row][start_col] = 0; } q_node start_node = q_node { .row = start_row, .col = start_col, .pos = start_pos, }; enq(start_node); while (!q_empty()) { q_node cur_node = deq(); if (cur_node.row == end_row && cur_node.col == end_col && cur_node.pos == pos_s) { return dist_s[end_row][end_col]; } // printf("%d,%d, pos %d\n", cur_node.row, cur_node.col, cur_node.pos); if (cur_node.pos == pos_s) { int cur_dist = dist_s[cur_node.row][cur_node.col]; // left if (valid_pos(cur_node.row, cur_node.col - 2, pos_h)) { if (dist_h[cur_node.row][cur_node.col - 2] == -1) { dist_h[cur_node.row][cur_node.col - 2] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col - 2, .pos = pos_h, }; enq(new_node); } } // right if (valid_pos(cur_node.row, cur_node.col + 1, pos_h)) { if (dist_h[cur_node.row][cur_node.col + 1] == -1) { dist_h[cur_node.row][cur_node.col + 1] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col + 1, .pos = pos_h, }; enq(new_node); } } // up if (valid_pos(cur_node.row - 2, cur_node.col, pos_v)) { if (dist_v[cur_node.row - 2][cur_node.col] == -1) { dist_v[cur_node.row - 2][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row - 2, .col = cur_node.col, .pos = pos_v, }; enq(new_node); } } // down if (valid_pos(cur_node.row + 1, cur_node.col, pos_v)) { if (dist_v[cur_node.row + 1][cur_node.col] == -1) { dist_v[cur_node.row + 1][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row + 1, .col = cur_node.col, .pos = pos_v, }; enq(new_node); } } } else if (cur_node.pos == pos_h) { int cur_dist = dist_h[cur_node.row][cur_node.col]; // left if (valid_pos(cur_node.row, cur_node.col - 1, pos_s)) { if (dist_s[cur_node.row][cur_node.col - 1] == -1) { dist_s[cur_node.row][cur_node.col - 1] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col - 1, .pos = pos_s, }; enq(new_node); } } // right if (valid_pos(cur_node.row, cur_node.col + 2, pos_s)) { if (dist_s[cur_node.row][cur_node.col + 2] == -1) { dist_s[cur_node.row][cur_node.col + 2] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col + 2, .pos = pos_s, }; enq(new_node); } } // up if (valid_pos(cur_node.row - 1, cur_node.col, pos_h)) { if (dist_h[cur_node.row - 1][cur_node.col] == -1) { dist_h[cur_node.row - 1][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row - 1, .col = cur_node.col, .pos = pos_h, }; enq(new_node); } } // down if (valid_pos(cur_node.row + 1, cur_node.col, pos_h)) { if (dist_h[cur_node.row + 1][cur_node.col] == -1) { dist_h[cur_node.row + 1][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row + 1, .col = cur_node.col, .pos = pos_h, }; enq(new_node); } } } else if (cur_node.pos == pos_v) { int cur_dist = dist_v[cur_node.row][cur_node.col]; // left if (valid_pos(cur_node.row, cur_node.col - 1, pos_v)) { if (dist_v[cur_node.row][cur_node.col - 1] == -1) { dist_v[cur_node.row][cur_node.col - 1] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col - 1, .pos = pos_v, }; enq(new_node); } } // right if (valid_pos(cur_node.row, cur_node.col + 1, pos_v)) { if (dist_v[cur_node.row][cur_node.col + 1] == -1) { dist_v[cur_node.row][cur_node.col + 1] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row, .col = cur_node.col + 1, .pos = pos_v, }; enq(new_node); } } // up if (valid_pos(cur_node.row - 1, cur_node.col, pos_s)) { if (dist_s[cur_node.row - 1][cur_node.col] == -1) { dist_s[cur_node.row - 1][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row - 1, .col = cur_node.col, .pos = pos_s, }; enq(new_node); } } // down if (valid_pos(cur_node.row + 2, cur_node.col, pos_s)) { if (dist_s[cur_node.row + 2][cur_node.col] == -1) { dist_s[cur_node.row + 2][cur_node.col] = cur_dist + 1; q_node new_node = q_node { .row = cur_node.row + 2, .col = cur_node.col, .pos = pos_s, }; enq(new_node); } } } else { // Should not be here } } return -1; } int main() { scanf("%d", &T); for (int _ = 0; _ < T; ++_) { // Initialize memset(map, 0, sizeof(map)); bool found_start = false; scanf("%d %d", &n, &m); // Read in map char linebuf[MAXN] = {0}; for (int i = 0; i < n; ++i) { scanf("%s", linebuf); for (int j = 0; j < m; ++j) { if (linebuf[j] == '#') { map[i][j] = 0; } else if (linebuf[j] == '.') { map[i][j] = 1; } else if (linebuf[j] == 'E') { map[i][j] = 2; } else if (linebuf[j] == 'X') { map[i][j] = 1; if (found_start == false) { start_row = i; start_col = j; start_pos = pos_s; // Assume this pos, if there are more X then change found_start = true; } else { if (j == start_col + 1 && i == start_row) { start_pos = pos_h; } else if (j == start_col && i == start_row + 1) { start_pos = pos_v; } else { // Should not be here } } } else if (linebuf[j] == 'O') { map[i][j] = 1; end_row = i; end_col = j; } } } int ans = bfs(); printf("%d\n", ans); } return 0; }