#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct Vertex {
size_t x;
size_t y;
} Vertex;
typedef struct Maze {
size_t width;
size_t height;
char const *maze;
Vertex start;
Vertex end;
} Maze;
char get_char(Maze const *m, size_t x, size_t y) { return m->maze[x + y * (m->width)]; }
bool is_digit(char c) { return '0' <= c && c <= '9'; }
Vertex find_destination(Maze const *m, size_t x, size_t y) {
assert(is_digit
(get_char
(m
, x
, y
))); for (size_t i = 0; i < m->width; ++i) {
for (size_t j = 0; j < m->height; ++j) {
if (get_char(m, i, j) == get_char(m, x, y)) {
if (i == x && j == y)
continue;
else
return (Vertex){ i, j };
}
}
}
}
Maze construct_maze(size_t width, size_t height, char const *maze) {
Maze m = { width, height, maze, { 0 }, { 0 } };
bool found_start = false;
bool found_end = false;
for (size_t i = 0; i < width; ++i) {
for (size_t j = 0; j < height; ++j) {
if (maze[i + j * width] == 'S') {
found_start = true;
m.start = (Vertex){ i, j };
if (found_end) goto done;
} else if (maze[i + j * width] == 'G') {
found_end = true;
m.end = (Vertex){ i, j };
if (found_start) goto done;
}
}
}
done:
return m;
}
typedef struct VertexLengthPair {
Vertex vertex;
size_t length;
} VertexLengthPair;
size_t list_adjacents(Maze const *m, Vertex const *v, Vertex *buffer) {
size_t len = 0;
if (v->x != 0) {
char c = get_char(m, v->x - 1, v->y);
if (is_digit(c)) {
buffer[len++] = find_destination(m, v->x - 1, v->y);
} else if(c != '#') {
buffer[len++] = (Vertex){ v->x - 1, v->y };
}
}
if (v->x != m->width - 1) {
char c = get_char(m, v->x + 1, v->y);
if (is_digit(c)) {
buffer[len++] = find_destination(m, v->x + 1, v->y);
} else if(c != '#') {
buffer[len++] = (Vertex){ v->x + 1, v->y };
}
}
if (v->y != 0) {
char c = get_char(m, v->x, v->y - 1);
if (is_digit(c)) {
buffer[len++] = find_destination(m, v->x, v->y - 1);
} else if(c != '#') {
buffer[len++] = (Vertex){ v->x, v->y - 1 };
}
}
if (v->y != m->height - 1) {
char c = get_char(m, v->x, v->y + 1);
if (is_digit(c)) {
buffer[len++] = find_destination(m, v->x, v->y + 1);
} else if(c != '#') {
buffer[len++] = (Vertex){ v->x, v->y + 1 };
}
}
return len;
}
bool equal_vertex(Vertex const *v, Vertex const *w) { return v->x == w->x && v->y == w->y; }
size_t find_shortest_path_length(Maze const *m) {
bool visited[m->width][m->height];
for (size_t i = 0; i < m->width; ++i)
for (size_t j = 0; j < m->height; ++j)
visited[i][j] = false;
VertexLengthPair queue[m->width * m->height];
VertexLengthPair *queue_front = queue;
VertexLengthPair *queue_last = queue + 1;
queue_front->vertex = m->start;
queue_front->length = 0;
visited[queue_front->vertex.x][queue_front->vertex.y] = true;
while (queue_front != queue_last) {
Vertex const v = queue_front->vertex;
size_t const next_length = queue_front->length + 1;
++queue_front;
Vertex buf[5];
size_t max = list_adjacents(m, &v, buf);
for (size_t i = 0; i < max; ++i) {
Vertex *w = buf + i;
if (visited[w->x][w->y])
continue;
if (equal_vertex(w, &(m->end)))
return next_length;
visited[w->x][w->y] = true;
queue_last->vertex = *w;
queue_last->length = next_length;
++queue_last;
}
}
return 0;
}
int main(void) {
size_t w, h;
scanf("%zu %zu%*c", &h
, &w
);
char maze[w * h];
for (size_t i = 0; i < h; ++i) {
scanf("%[^\n]%*c", maze
+ i
* w
); }
Maze m = construct_maze(w, h, maze);
size_t len = find_shortest_path_length(&m);
if (len)
else
return 0;
}
CiNpbmNsdWRlIDxhc3NlcnQuaD4KI2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCnR5cGVkZWYgc3RydWN0IFZlcnRleCB7CiAgc2l6ZV90IHg7CiAgc2l6ZV90IHk7Cn0gVmVydGV4OwoKdHlwZWRlZiBzdHJ1Y3QgTWF6ZSB7CiAgc2l6ZV90IHdpZHRoOwogIHNpemVfdCBoZWlnaHQ7CgogIGNoYXIgY29uc3QgKm1hemU7CiAgCiAgVmVydGV4IHN0YXJ0OwogIFZlcnRleCBlbmQ7Cn0gTWF6ZTsKCmNoYXIgZ2V0X2NoYXIoTWF6ZSBjb25zdCAqbSwgc2l6ZV90IHgsIHNpemVfdCB5KSB7IHJldHVybiBtLT5tYXplW3ggKyB5ICogKG0tPndpZHRoKV07IH0KCmJvb2wgaXNfZGlnaXQoY2hhciBjKSB7IHJldHVybiAnMCcgPD0gYyAmJiBjIDw9ICc5JzsgfQoKVmVydGV4IGZpbmRfZGVzdGluYXRpb24oTWF6ZSBjb25zdCAqbSwgc2l6ZV90IHgsIHNpemVfdCB5KSB7CiAgYXNzZXJ0KGlzX2RpZ2l0KGdldF9jaGFyKG0sIHgsIHkpKSk7CiAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBtLT53aWR0aDsgKytpKSB7CiAgICBmb3IgKHNpemVfdCBqID0gMDsgaiA8IG0tPmhlaWdodDsgKytqKSB7CiAgICAgIGlmIChnZXRfY2hhcihtLCBpLCBqKSA9PSBnZXRfY2hhcihtLCB4LCB5KSkgewoJaWYgKGkgPT0geCAmJiBqID09IHkpCgkgIGNvbnRpbnVlOwoJZWxzZQoJICByZXR1cm4gKFZlcnRleCl7IGksIGogfTsKICAgICAgfQogICAgfQogIH0KICBhc3NlcnQoZmFsc2UpOwp9CgpNYXplIGNvbnN0cnVjdF9tYXplKHNpemVfdCB3aWR0aCwgc2l6ZV90IGhlaWdodCwgY2hhciBjb25zdCAqbWF6ZSkgewogIE1hemUgbSA9IHsgd2lkdGgsIGhlaWdodCwgbWF6ZSwgeyAwIH0sIHsgMCB9IH07CiAgYm9vbCBmb3VuZF9zdGFydCA9IGZhbHNlOwogIGJvb2wgZm91bmRfZW5kID0gZmFsc2U7CiAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCB3aWR0aDsgKytpKSB7CiAgICBmb3IgKHNpemVfdCBqID0gMDsgaiA8IGhlaWdodDsgKytqKSB7CiAgICAgIGlmIChtYXplW2kgKyBqICogd2lkdGhdID09ICdTJykgewoJZm91bmRfc3RhcnQgPSB0cnVlOwoJbS5zdGFydCA9IChWZXJ0ZXgpeyBpLCBqIH07CglpZiAoZm91bmRfZW5kKSBnb3RvIGRvbmU7CiAgICAgIH0gZWxzZSBpZiAobWF6ZVtpICsgaiAqIHdpZHRoXSA9PSAnRycpIHsKCWZvdW5kX2VuZCA9IHRydWU7CgltLmVuZCA9IChWZXJ0ZXgpeyBpLCBqIH07CglpZiAoZm91bmRfc3RhcnQpIGdvdG8gZG9uZTsKICAgICAgfQogICAgfQogIH0KIGRvbmU6CiAgcmV0dXJuIG07Cn0KCnR5cGVkZWYgc3RydWN0IFZlcnRleExlbmd0aFBhaXIgewogIFZlcnRleCB2ZXJ0ZXg7CiAgc2l6ZV90IGxlbmd0aDsKfSBWZXJ0ZXhMZW5ndGhQYWlyOwoKc2l6ZV90IGxpc3RfYWRqYWNlbnRzKE1hemUgY29uc3QgKm0sIFZlcnRleCBjb25zdCAqdiwgVmVydGV4ICpidWZmZXIpIHsKICBzaXplX3QgbGVuID0gMDsKICBpZiAodi0+eCAhPSAwKSB7CiAgICBjaGFyIGMgPSBnZXRfY2hhcihtLCB2LT54IC0gMSwgdi0+eSk7CiAgICBpZiAoaXNfZGlnaXQoYykpIHsKICAgICAgYnVmZmVyW2xlbisrXSA9IGZpbmRfZGVzdGluYXRpb24obSwgdi0+eCAtIDEsIHYtPnkpOwogICAgfSBlbHNlIGlmKGMgIT0gJyMnKSB7CiAgICAgIGJ1ZmZlcltsZW4rK10gPSAoVmVydGV4KXsgdi0+eCAtIDEsIHYtPnkgfTsKICAgIH0KICB9CiAgaWYgKHYtPnggIT0gbS0+d2lkdGggLSAxKSB7CiAgICBjaGFyIGMgPSBnZXRfY2hhcihtLCB2LT54ICsgMSwgdi0+eSk7CiAgICBpZiAoaXNfZGlnaXQoYykpIHsKICAgICAgYnVmZmVyW2xlbisrXSA9IGZpbmRfZGVzdGluYXRpb24obSwgdi0+eCArIDEsIHYtPnkpOwogICAgfSBlbHNlIGlmKGMgIT0gJyMnKSB7CiAgICAgIGJ1ZmZlcltsZW4rK10gPSAoVmVydGV4KXsgdi0+eCArIDEsIHYtPnkgfTsKICAgIH0KICB9CiAgaWYgKHYtPnkgIT0gMCkgewogICAgY2hhciBjID0gZ2V0X2NoYXIobSwgdi0+eCwgdi0+eSAtIDEpOwogICAgaWYgKGlzX2RpZ2l0KGMpKSB7CiAgICAgIGJ1ZmZlcltsZW4rK10gPSBmaW5kX2Rlc3RpbmF0aW9uKG0sIHYtPngsIHYtPnkgLSAxKTsKICAgIH0gZWxzZSBpZihjICE9ICcjJykgewogICAgICBidWZmZXJbbGVuKytdID0gKFZlcnRleCl7IHYtPngsIHYtPnkgLSAxIH07CiAgICB9CiAgfQogIGlmICh2LT55ICE9IG0tPmhlaWdodCAtIDEpIHsKICAgIGNoYXIgYyA9IGdldF9jaGFyKG0sIHYtPngsIHYtPnkgKyAxKTsKICAgIGlmIChpc19kaWdpdChjKSkgewogICAgICBidWZmZXJbbGVuKytdID0gZmluZF9kZXN0aW5hdGlvbihtLCB2LT54LCB2LT55ICsgMSk7CiAgICB9IGVsc2UgaWYoYyAhPSAnIycpIHsKICAgICAgYnVmZmVyW2xlbisrXSA9IChWZXJ0ZXgpeyB2LT54LCB2LT55ICsgMSB9OwogICAgfQogIH0KICByZXR1cm4gbGVuOwp9Cgpib29sIGVxdWFsX3ZlcnRleChWZXJ0ZXggY29uc3QgKnYsIFZlcnRleCBjb25zdCAqdykgeyByZXR1cm4gdi0+eCA9PSB3LT54ICYmIHYtPnkgPT0gdy0+eTsgfQoKc2l6ZV90IGZpbmRfc2hvcnRlc3RfcGF0aF9sZW5ndGgoTWF6ZSBjb25zdCAqbSkgewogIGJvb2wgdmlzaXRlZFttLT53aWR0aF1bbS0+aGVpZ2h0XTsKICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IG0tPndpZHRoOyArK2kpCiAgICBmb3IgKHNpemVfdCBqID0gMDsgaiA8IG0tPmhlaWdodDsgKytqKQogICAgICB2aXNpdGVkW2ldW2pdID0gZmFsc2U7CiAgVmVydGV4TGVuZ3RoUGFpciBxdWV1ZVttLT53aWR0aCAqIG0tPmhlaWdodF07CiAgVmVydGV4TGVuZ3RoUGFpciAqcXVldWVfZnJvbnQgPSBxdWV1ZTsKICBWZXJ0ZXhMZW5ndGhQYWlyICpxdWV1ZV9sYXN0ID0gcXVldWUgKyAxOwogIHF1ZXVlX2Zyb250LT52ZXJ0ZXggPSBtLT5zdGFydDsKICBxdWV1ZV9mcm9udC0+bGVuZ3RoID0gMDsKICB2aXNpdGVkW3F1ZXVlX2Zyb250LT52ZXJ0ZXgueF1bcXVldWVfZnJvbnQtPnZlcnRleC55XSA9IHRydWU7CiAgCiAgd2hpbGUgKHF1ZXVlX2Zyb250ICE9IHF1ZXVlX2xhc3QpIHsKICAgIFZlcnRleCBjb25zdCB2ID0gcXVldWVfZnJvbnQtPnZlcnRleDsKICAgIHNpemVfdCBjb25zdCBuZXh0X2xlbmd0aCA9IHF1ZXVlX2Zyb250LT5sZW5ndGggKyAxOwogICAgKytxdWV1ZV9mcm9udDsKICAgIAogICAgVmVydGV4IGJ1Zls1XTsgICAgCiAgICBzaXplX3QgbWF4ID0gbGlzdF9hZGphY2VudHMobSwgJnYsIGJ1Zik7CiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IG1heDsgKytpKSB7CiAgICAgIFZlcnRleCAqdyA9IGJ1ZiArIGk7CiAgICAgIGlmICh2aXNpdGVkW3ctPnhdW3ctPnldKQoJY29udGludWU7CiAgICAgIGlmIChlcXVhbF92ZXJ0ZXgodywgJihtLT5lbmQpKSkKCXJldHVybiBuZXh0X2xlbmd0aDsKCiAgICAgIHZpc2l0ZWRbdy0+eF1bdy0+eV0gPSB0cnVlOwogICAgICBxdWV1ZV9sYXN0LT52ZXJ0ZXggPSAqdzsKICAgICAgcXVldWVfbGFzdC0+bGVuZ3RoID0gbmV4dF9sZW5ndGg7CiAgICAgICsrcXVldWVfbGFzdDsKICAgIH0KICB9CiAgcmV0dXJuIDA7Cn0KCmludCBtYWluKHZvaWQpIHsKICBzaXplX3QgdywgaDsKICBzY2FuZigiJXp1ICV6dSUqYyIsICZoLCAmdyk7CgogIGNoYXIgbWF6ZVt3ICogaF07CiAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBoOyArK2kpIHsKICAgIHNjYW5mKCIlW15cbl0lKmMiLCBtYXplICsgaSAqIHcpOwogIH0KICAKICBNYXplIG0gPSBjb25zdHJ1Y3RfbWF6ZSh3LCBoLCBtYXplKTsKCiAgc2l6ZV90IGxlbiA9IGZpbmRfc2hvcnRlc3RfcGF0aF9sZW5ndGgoJm0pOwogIGlmIChsZW4pCiAgICBwcmludGYoIiV6dVxuIiwgbGVuKTsKICBlbHNlCiAgICBwdXRzKCJpbXBvc3NpYmxlIik7CiAgCiAgcmV0dXJuIDA7Cn0K