백준의 움직이는 미로탈출(16954) 문제이다.

[ 문제 바로가기 ]


[ 문제풀이 ]

1) 벽이 1초마다 한칸씩 아래로 내려오는 상황에서, 도착점에 도달할 수 있는지 구해야 하는 문제이다.

   먼저, 본인은 이 문제를 해결하기 위해서 먼저 벽의 맵을 따로 만들어 주었다.

   벽의 맵은 3차원으로 이루어져있으며 Wall_MAP[a][b][c] = '.' or '#' 의 의미는

   'a'초 일 때, (b, c)는 빈 공간이거나 벽입니다 를 의미한다.

   이 후에, 사람을 이 벽의 맵과 비교하면서 움직이는 식으로 구현을 해 주었다.

  

2) 본격적인 구현에 들어가보자. 먼저, 벽의 맵을 만들어보자.

   벽의 맵을 만들기 위해서 본인은 먼저 입력과 동시에 벽의 위치를 Vetor에 저장해 주었다.

   이 Vector에 저장된 각각의 좌표들을 이용해서 3차원 Wall_MAP에 저장해 주었다.

   이 후, 사람을 움직이는 것은 BFS탐색을 통해서 구현해 주었다.

   BFS탐색을 할 때에는 2가지를 고려해 주었다.

   먼저 첫 번째는 현재 (x, y)에 있고, t초라고 가정할 때, t + 1초에 (x + 방향, y + 방향) 으로 움직였을 때, 그 칸이

   벽이 없는지(Wall_MAP[t+1][x+방향][y+방향] == '.') 를 고려해 주었다.

   사실 처음에는 이거 한가지만 비교를 해 주었는데, 이러면 틀리게 된다. 얼핏보면 저 조건만 비교해준다면 맞을 것

   같지만 예제입력2를 한번 봐보도록 하자.

  

    예제입력2는 위와같은 형태이고, 시작점을 O로 표시해보았다.

    그렇다면 벽의 맵을 한번 생각해보자. 0초일 때 벽의 맵은 위와 같은 형태일 것이고, 1초일 때를 생각해보자.

   

    1초일 때는 다음과 같은 형태이다. 그렇다면, 여기서 빨강색으로 표시된 (6, 0)과 (6, 1)에 주목해보자.

    분명, 1초일 때, 저 (6, 0)과 (6, 1)은 빈 공간이라서 사람이 갈 수 있는 곳으로 표시가 되어있다.

    하지만 ! 0초일 때의 맵을 한번 봐보자. 사람이 1초에 저기로 갈 수 있을까?? 딱 봐도 갈 수 없다는 것을 알 수 있다.

    즉, " 사람이 이동하려는 곳의 좌표가 현재 시간에 벽이면 움직일 수 없다 ! " 라는 것을 알 수 있다.

    이 2가지만 생각해 주면 된다. 또한, 일반적인 문제들과 같이 한번 방문한 지점을 재방문 하지 못하게 하면 안된다.

   

    마지막으로 BFS탐색의 종료조건은 다음과 같다. 사람이 가장 오른쪽 위의 좌표에 도착하는 경우는 물론이고,

    사람이 가장 윗줄로만 도착하더라도 사실 도착지에 도착할 수 있다. 사람이 어떻게 어떻게 올라가서 (0, 0)까지 갔다고

    생각해보자. 당연히 더 이상 내려올 벽은 없을 것이고, (0, 0)에서 (0, 7)까지 이동하는 것도 탐색에 추가시킨다면

    시간 낭비일 것이다. 사람이 가장 윗줄에만 도착한다면 (0, 7)이 아니더라도 도착지에 도착할 수가 있다.

    또 하나는 현재 사람이 있는 줄보다 위에 있는 줄을 모두 비교했을 때 벽이 더이상 없는 경우이다.

    모든 맵이 '.' 으로만 입력되어 있는 예제입력1을 봐보도록 하자. 굳이 탐색을 해야 도착하는지 알 수 있을까??

    아니다. 무조건 도착점에 도달할 수가 있다. 왜냐하면 현재 사람이 있는 지점 윗줄들에 벽이 하나도 없기 때문이다.

    이러한 맵을 생각해보자. 1초 후에 사람이 갈 수 있는 곳과 벽의 상태를

     표시해보면 다음과 같아진다.

    

      1초 후에 사람이 움직일 수 있는 곳은 O친 2곳이 될 것이며, 벽은 저렇게 내려오게 될 것이다.

      그렇다면, 저 상태에서 탐색을 더 해봐야 도착점에 도착하는지 알 수 있을까?? 아니다. 무조건 도착할 수 있다는 것을

      알 수 있다. 왜냐하면 사람이 있는 지점보다 윗줄에 벽이 더 이상 존재하지 않기 때문이다.

      따라서 본인은

      1. 사람이 제일 윗줄에 도착했을 경우

      2. 사람이 있는 좌표를 기준으로 그 윗줄에 벽이 하나도 없는 경우

      이 2가지를 종료조건으로 만들어 주었다.


[ 소스코드 ]

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include<iostream>
#include<queue>
#include<vector>
 
#define endl "\n"
#define MAX 8
using namespace std;
 
char MAP[MAX][MAX];
char Wall_MAP[MAX][MAX][MAX];
vector<pair<intint>> Wall_V;
 
int dx[] = { -1-1-1001110 };
int dy[] = { -101-11-1010 };
 
void Input()
{
    for (int i = 0; i < MAX; i++)
    {
        for (int j = 0; j < MAX; j++)
        {
            cin >> MAP[i][j];
            if (MAP[i][j] == '#')
            {
                Wall_MAP[0][i][j] = '#';
                Wall_V.push_back(make_pair(i, j));
            }
        }
    }
    for (int t = 0; t < MAX; t++)
    {
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
            {
                if (Wall_MAP[t][i][j] == '#'continue;
                Wall_MAP[t][i][j] = '.';
            }
        }
    }
}
 
void Make_Wall_MAP()
{
    for (int i = 0; i < Wall_V.size(); i++)
    {
        int x = Wall_V[i].first;
        int y = Wall_V[i].second;
        int Time = 1;
 
        while (1)
        {
            int nx = x + 1;
            int ny = y;
            if (nx >= MAX) break;
            
            Wall_MAP[Time][nx][ny] = '#';
            Time++;
            x = nx;
            y = ny;
        }
    }
}
 
void Print()
{
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            for (int k = 0; k < 8; k++)
            {
                cout << Wall_MAP[i][j][k] << " ";
            }
            cout << endl;
        }
        cout << "#######################################" << endl;
    }
}
 
bool Can_Finish(int x, int T)
{
    for (int i = x - 1; i >= 0; i--)
    {
        for (int j = 0; j < MAX; j++)
        {
            if (Wall_MAP[T][i][j] == '#'return false;
        }
    }
    return true;
}
 
int BFS(int a, int b)
{
    queue<pair<pair<intint>int>> Q;
    Q.push(make_pair(make_pair(a, b), 0));
 
    while (Q.empty() == 0)
    {
        int x = Q.front().first.first;
        int y = Q.front().first.second;
        int t = Q.front().second;
        Q.pop();
 
        if (x == 0return 1;
        else
        {
            if (Can_Finish(x, t) == truereturn 1;
        }
        
        for (int i = 0; i < 9; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            int nt = t + 1;
 
            if (nx >= 0 && ny >= 0 && nx < MAX && ny < MAX)
            {
                if (Wall_MAP[nt][nx][ny] == '.' && Wall_MAP[t][nx][ny] == '.')
                {
                    Q.push(make_pair(make_pair(nx, ny), nt));
                }
            }
        }
    }
    return 0;
}
 
bool Wall_State()
{
    for (int i = 0; i < 7; i++)
    {
        int Cnt = 0;
        for (int j = 0; j < MAX; j++)
        {
            if (MAP[i][j] == '#') Cnt++;
        }
        if (Cnt == 8return false;
    }
    return true;
}
 
//(x,y) 말고 
void Solution()
{
    if (Wall_V[0].size() == 0)
    {
        cout << 1 << endl;
        return;
    }
    if (Wall_State() == false)
    {
        cout << 0 << endl;
        return;
    }
    Make_Wall_MAP();
    cout << BFS(70<< endl;
}
 
void Solve()
{
    Input();
    Solution();
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    //freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
cs






+ Recent posts