백준의 구슬탈출2(13460) 문제이다.

[ 문제 바로가기 ]


- 13459번 문제인 구슬탈출 문제에 대한 풀이는 아래와 같습니다. 사실 정답을 출력시키는 것만 다르고 모든 풀이법이

   똑같기 때문에 아래 설명을 읽으시면 13459번 구슬탈출 문제도 푸실 수 있을 것입니다. -

[ 구슬탈출(13459) 바로가기 ]


[ 문제풀이 ]

1) 본인은 이 문제를 재귀를 통한 완전탐색으로 진행해 보았다. 어떤식으로 진행이 되는지 천천히 알아보자.

    가장 먼저, 빨간공 파란공이 있는 위치에서 동서남북 총 4방향으로 움직여보는 것을 시작으로 한다.

    참고로 본인은 맵에서 R과 B는 없애버렸고 그 좌표만으로 모든 것을 계산해 주었다.

    움직이는 함수의 진행과정은 다음과 같다.

    1. 빨간공을 진행방향으로 움직인다. 이 과정에서 빨간공이 구멍에 빠지게 되면 구멍에 빠졋다고 표시를 해준다.

    2. 파란공을 진행방향으로 움직인다. 이 과정에서 파란공이 구멍에 빠지게 되면 구멍에 빠졌다고 표시를 해준다.

    3. 파란공이 구멍에 빠졌다면 그대로 그 함수를 끝내준다.

       왜냐하면 빨간공이 빠지든 말든 상관없이 파란공이 빠졌다는 것은 잘못된 방향으로 움직였다는 의미이기 때문이다.

    4. 파란공이 구멍에 빠지지 않았는데 빨간공이 빠졌다면 기존의 기울인 횟수와 비교해서 값을 갱신시켜준다.

    5. 위의 두 경우 모두 아니라면, 즉 그 어떤공도 구멍에 빠지지 않았다면 빨간공과 파란공의 좌표를 비교해준다.

        갑자기 왜 좌표를 비교할까?? R과 B가 겹쳐지는 경우가 존재할 수 있기 때문이다. 물론 이건 본인 처럼 구현했을

        때이다. 처음에 말했듯이 본인의 맵에서 R과 B는 없다. 오직 '#' , '.' , 'O' 뿐이다.

        따라서, 두 공 모두 구멍에 빠지지 않았다면 벽에 부딪혀서 멈추게 된 경우일 것이다.

        #RB...# 이런 맵이 있을 때 이거를 본인의 맵으로 바꿔보면 #.....# 이 될 것이고 오른쪽으로 기울였을 때 결과상태는

        #...RB# 가 될 것이다. 하지만, 본인의 맵에서는 아마 R과 B가 겹쳐있는 형태일 것이다.

       따라서, 빨간공과 움직인 거리와 파란공이 움직인 거리를 비교해서 더 많이 움직인 놈을 한칸 뒤로 땡겨주었다.

       위의 경우로 설명을 하자면, R은 총 4칸을 움직였고 B는 3칸을 움직였다. 즉, R이 더 많이 움직였으므로

       한 칸 뒤로 땡겨서 #...RB#와 같은 형태로 만들어준 것이다.

    6. 위의 과정이 끝났으면 움직인 R과 B의 좌표로 움직이는 함수를 재귀적으로 호출하는데 이 때는 방향을 신경써주어야

        한다.

        생각을 해보자. 우리가 예를 들어 오른쪽으로 공을 움직였다고 생각해보자. 그 다음 턴에서 왼쪽으로 공을 움직이는게

        의미가 있을까?? 아니다. 다시 제자리로 돌아가는 움직임이기 때문에 의미가 없다.

        또한 이 상태에서 오른쪽으로 또 움직이는것 또한 의미가 있을까?? 아니다. 지금 오른쪽으로 더 이상 갈 곳이 없어서

        멈춰있는 상태인데 이 상태에서 오른쪽으로 또 움직이는 것은 의미가 없다.

        즉, 현재 움직인 방향과, 현재 움직인 방향의 반대방향으로는 그 다음 턴에서는 움직일 수 없게 해 주었다.


2) 위의 내용을 재귀로 호출하면서 반복하면된다. 물론 10번이상 움직인 경우는 의미가 없으므로, 현재 움직인 횟수가 10번

    이상이면 탐색할 것도 없이 return 시켜주었다.


[ 소스코드 ]

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
#include<iostream>
 
#define endl "\n"
#define MAX 10
using namespace std;
 
int N, M, Answer = 987654321;
char MAP[MAX][MAX];
 
int dx[] = { 001-1 };
int dy[] = { 1-100 };
 
pair<intint> Red, Blue;
 
int Min(int A, int B) { if (A < B) return A; return B; }
 
void Input()
{
    cin >> N >> M;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            cin >> MAP[i][j];
            if (MAP[i][j] == 'R')
            {
                Red.first = i;
                Red.second = j;
                MAP[i][j] = '.';
            }
            else if (MAP[i][j] == 'B')
            {
                Blue.first = i;
                Blue.second = j;
                MAP[i][j] = '.';
            }
        }
    }
}
 
int Move_Dist(int x, int y, int xx, int yy)
{
    return abs(x - xx) + abs(y - yy);
}
 
int Inverse_Direction(int Cur_D)
{
    if (Cur_D == 0return 1;
    else if (Cur_D == 1return 0;
    else if (Cur_D == 2return 3;
    else if (Cur_D == 3return 2;
}
 
void Move(int Rx, int Ry, int Bx, int By, int Cnt, int dir)
{
    if (Cnt >= Answer) return;
    if (Cnt > 10return;
 
    bool Red_Flag = false;
    bool Blue_Flag = false;
 
    int nRx = Rx + dx[dir];
    int nRy = Ry + dy[dir];
    while (1)
    {
        if (MAP[nRx][nRy] == '#'break;
        if (MAP[nRx][nRy] == 'O')
        {
            Red_Flag = true;
            break;
        }
        nRx = nRx + dx[dir];
        nRy = nRy + dy[dir];
    }
    nRx = nRx - dx[dir];
    nRy = nRy - dy[dir];
 
    int nBx = Bx + dx[dir];
    int nBy = By + dy[dir];
    while (1)
    {
        if (MAP[nBx][nBy] == '#'break;
        if (MAP[nBx][nBy] == 'O')
        {
            Blue_Flag = true;
            break;
        }
        nBx = nBx + dx[dir];
        nBy = nBy + dy[dir];
    }
    nBx = nBx - dx[dir];
    nBy = nBy - dy[dir];
 
    if (Blue_Flag == truereturn;
    else
    {
        if (Red_Flag == true)
        {
            Answer = Min(Answer, Cnt);
            return;
        }
    }
 
    if (nRx == nBx && nRy == nBy)
    {
        int Red_Dist = Move_Dist(Rx, Ry, nRx, nRy);
        int Blue_Dist = Move_Dist(Bx, By, nBx, nBy);
 
        if (Red_Dist > Blue_Dist)
        {
            nRx = nRx - dx[dir];
            nRy = nRy - dy[dir];
        }
        else
        {
            nBx = nBx - dx[dir];
            nBy = nBy - dy[dir];
        }
    }
 
 
    for (int i = 0; i < 4; i++)
    {
        if (i == dir) continue;
        if (i == Inverse_Direction(dir)) continue;
 
        Move(nRx, nRy, nBx, nBy, Cnt + 1, i);
    }
}
 
void Solution()
{
    for (int i = 0; i < 4; i++)
    {
        int x = Red.first;
        int y = Red.second;
        int xx = Blue.first;
        int yy = Blue.second;
 
        Move(x, y, xx, yy, 1, i);
    }
 
    if (Answer > 10 || Answer == 987654321) Answer = -1;
    cout << Answer << 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