#include #include #include #define BOARD_SIZE 141 #define CHEAT_LENGTH 20 #define IN_BOUND(x, y) (x < BOARD_SIZE && x >= 0 && y < BOARD_SIZE && y >= 0) #define MIN(a,b) (((a)<(b))?(a):(b)) struct coordinate { int x, y; }; struct coordinate queue[10000]; int queue_len; int queue_start; char map[BOARD_SIZE][BOARD_SIZE]; int values[BOARD_SIZE][BOARD_SIZE]; struct coordinate cheat_deltas[10000]; int num_cheat_deltas; int queue_pop(struct coordinate *coord) { if (queue_len == 0) { return -1; } memcpy(coord, &queue[queue_start], sizeof(struct coordinate)); queue_start++; queue_len--; return 0; } void queue_push(struct coordinate *coord) { //printf("%d, %da\n", coord->x, coord->y); memcpy(&queue[queue_start + queue_len], coord, sizeof(struct coordinate)); queue_len++; } void check_and_push(struct coordinate *coord, int depth) { //printf("%d\n", depth); if (!IN_BOUND(coord->x, coord->y) || map[coord->x][coord->y] == '#') { return; } if (values[coord->x][coord->y] == 100000) { //printf("%d\n", depth); values[coord->x][coord->y] = depth + 1; queue_push(coord); } } int dfs(struct coordinate coord) { queue_push(&coord); values[coord.x][coord.y] = 0; while (!queue_pop(&coord)) { //printf("%d, %d!", coord.x, coord.y); int value = values[coord.x][coord.y]; //printf("%d, %d: %d\n", coord.x, coord.y, values[coord.x][coord.y]); coord.x++; check_and_push(&coord, value); coord.x -= 2; check_and_push(&coord, value); coord.x++; coord.y++; check_and_push(&coord, value); coord.y -= 2; check_and_push(&coord, value); coord.y++; } return 0; } int cheats = 0; int test_cheat(int x, int y, int value, int dist) { int v; if (IN_BOUND(x, y) && (map[x][y] == '.' || map[x][y] == 'E') && (v = values[x][y] - value) > dist) { v -= dist; //printf("cheat: %d\n", v, x, y); if (v >= 100) { cheats++; } return v; } return 0; } int test_next(int x, int y, int value) { //printf("%d, %d\n", value, values[x][y]); return (IN_BOUND(x, y) && map[x][y] == '.' && values[x][y] - value == 1); } int find_cheat(int x, int y) { printf("%d, %d ", x, y); printf("%c\n", map[x][y]); if (!IN_BOUND(x, y)) { return 0; } int value = values[x][y]; int v; for (int i = 0; i < num_cheat_deltas; i++) { //printf("%d, %d\n", x + cheat_deltas[i].x, y + cheat_deltas[i].y); test_cheat(x + cheat_deltas[i].x, y + cheat_deltas[i].y, value, abs(cheat_deltas[i].x) + abs(cheat_deltas[i].y)); } if (test_next(x + 1, y, value)) { return find_cheat(x + 1, y); } if (test_next(x - 1, y, value)) { return find_cheat(x - 1, y); } if (test_next(x, y + 1, value)) { return find_cheat(x, y + 1); } if (test_next(x, y - 1, value)) { return find_cheat(x, y - 1); } return 0; } int main() { // calc cheats for (int x = -CHEAT_LENGTH; x <= CHEAT_LENGTH; x++) { for (int y = -CHEAT_LENGTH; y <= CHEAT_LENGTH; y++) { if (abs(x) + abs(y) <= CHEAT_LENGTH) { //printf("%d, %d\n", x, y); cheat_deltas[num_cheat_deltas].x = x; cheat_deltas[num_cheat_deltas].y = y; num_cheat_deltas++; } } } //exit(0); char *line_buf = NULL; size_t buffer_size = 100; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { map[i][j] = '.'; values[i][j] = 100000; } } struct coordinate coords[10000]; int num_cords = 0; struct coordinate start, end; int y = 0; while (getline(&line_buf, &buffer_size, stdin) > 0) { printf(line_buf); for (int x = 0; x < BOARD_SIZE; x++) { map[x][y] = line_buf[x]; if (line_buf[x] == 'S') { start.x = x; start.y = y; } if (line_buf[x] == 'E') { end.x = x; end.y = y; } } y++; } dfs(start); find_cheat(start.x, start.y); printf("res: %d", cheats); }