벽 부수고 이동하기
20 October 2019
문제 : https://www.acmicpc.net/problem/2206
이번은 "현재 상태"를 정점으로 표현하여 그래프를 만들고 최단거리를 구하는 문제를 풀어보도록 하겠습니다.
#include<stdio.h>
static int X, Y;
int head = 0;
int tail = 0;
int visit[1001][1001][2] = { 0 };
int **mat;
const int arr_size = 1000001;
int bfs();
struct Node
{
int x, y, z, u;
Node* myAlloc(int x, int y, int z, int u) {
this->x = x;
this->y = y;
this->z = z;
this->u = u;
return this;
}
}a[arr_size];
void add(int x, int y, int z, int u) {
if (tail >= arr_size)
{
tail -= arr_size;
}
a[tail++].myAlloc(x, y, z, u);
}
Node* pull() {
if (head == tail)
{
return NULL;
}
if (head >= arr_size)
{
head -= arr_size;
}
return &a[head++];
}
int main(void) {
scanf("%d %d", &X, &Y);
mat = new int*[X];
for (int i = 0; i < X; i++)
{
mat[i] = new int[Y];
for (int k = 0; k < Y; k++)
{
scanf("%1d", &mat[i][k]);
}
}
add(0, 0, 0, 1);
printf("%d", bfs());
}
void move(int x, int y, int z, int u) {
if (x < 0 || y < 0 || x >= X || y >= Y)
{
return;
}
if (visit[x][y][z] != 0)
{
return;
}
if (mat[x][y] == 1)
{
if (z > 0) {
return;
}
z = 1;
}
visit[x][y][z] = 1;
add(x, y, z, u);
}
int bfs() {
Node* node = pull();
while (node != NULL)
{
if (node->x == X - 1 && node->y == Y - 1)
{
return node->u;
}
move(node->x - 1, node->y, node->z, node->u + 1);
move(node->x + 1, node->y, node->z, node->u + 1);
move(node->x, node->y - 1, node->z, node->u + 1);
move(node->x, node->y + 1, node->z, node->u + 1);
node = pull();
}
return -1;
}
먼저 Node를 선언하여, Circullar Queue를 생성하여 줍니다.가장 먼저, 큐에 최초 시작하는 지점을 x,y, 현재 이동한 카운트, 즉 처음에는 0을 넣어줍니다.
해당 지점에서 사방으로 이동이 가능하므로, 상하좌우 지점을 체크해주도록 합니다.
해당 값이 1인 경우, 한번만 벽을 부술 수 있으므로 z를 1로 셋팅해주고, visit 항목도 해당 값이 0과 1인 경우로 두개로 체크해주도록 합니다.
해당 로직이 모두 수행된 이후까지 마지막 지점 값이 나오지 않으면 -1을 return해주도록 합니다.