백준의 돌그룹(12886) 문제이다.

( 문제 바로가기 )


[ 문제풀이 ]

1) 이 문제는 3개의 돌 그룹 중에서, 2개의 그룹을 골라, 더 큰 쪽의 돌그룹에서 더 작은 쪽의 돌그룹으로 작은쪽 돌그룹의 돌 갯

   수 만큼 준다고 했을 때, 3개의 돌 그룹의 갯수가 모두 같아지는 경우를 찾아야 하는 문제이다.

   BFS를 통해서 구현할 수 있으며, Queue에서는 3개의 돌그룹에 담겨져 있는 돌의 갯수를 관리해 주었다.


2) Queue 반복문 안에서는 모든 조건에 대해 참일 경우 모든 경우에 대해서 다 해보면 된다.

   예를 들어서, A B C 3개의 돌그룹이 있다고 생각해보자.

   BFS의 반복문 안에서는

   1. A < B 인 경우

   2. B < A 인 경우

   3. A < C 인 경우

   4. C < A 인 경우

   5. B < C 인 경우

   6. C < B 인 경우

   이렇게 6개의 경우에 대해서 문제에서 돌의 갯수를 옮겨주라는 대로 옮겨주면 된다. 이 부분은 어렵지 않다.


3) 사실상 이 문제의 어려운 부분은 메모리초과 혹은 시간초과라고 생각한다. 실제로 본인은 이 문제를 풀면서 메모리초과

   시간초과 다떴었다... 3개의 돌그룹에서 중복을 관리하는 부분이 조금 애매하다고 생각한다.

   본인은 처음에 중복을 체크하지 않고, 위의 6개의 조건문만 계속 돌리면서 돌을 옮겨주는 식으로 구현하였는데

   이 때는 메모리초과가 났었다. 또한 시간이 너무 오래걸릴 것 같아서, 임의로 step을 만들어서 Queue의 반복문이

   2000번 이상 돌지 못하게 구현해 보았다. 이 경우에는 시간도 빨리 해결되고 정답 처리를 받을 수 있었지만, 사실상

   이 문제에 대한 테스트케이스가 운이 좋게 2000번 넘는 것이 없어서 정답을 받았을 뿐, 이 문제에 대한 정확한 정답이라고

   생각하지 않았다. 아 물론, 일반적으로 사용하는 Visiti[][][] 3차원 배열을 이용해서 중복 체크를 하려고 했으나, 돌의 갯수

   가 너무 커서 배열로는 감당하기 힘든 크기라서 할 수 없었다.

   그래서 본인은 set을 사용하였다. 3개의 변수를 set으로 관리해주었고, 중복된 조합에 대해서는 Queue에 넣지 않도록

   체크해 주었더니, 정답처리를 받았으나, 메모리와 시간을 엄청나게 받았다.

   이 부분에 대해서는 본인도 정확한 풀이를 잘 모르겠다....


[ 소스코드 ]

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
#include<iostream>
#include<queue>
#include<set>
 
typedef long long ll;
#define endl "\n"
#define MAX 500 + 1
using namespace std;
 
ll A, B, C;
set<pair<pair<ll, ll>, ll>> Visit;
 
void Input()
{
    cin >> A >> B >> C;
}
 
void Solution()
{
    bool Can_Answer = false;
    queue<pair<pair<ll, ll>, ll>> Q;
    Q.push(make_pair(make_pair(A, B), C));
    Visit.insert(make_pair(make_pair(A, B), C));
 
    while (Q.empty() == 0)
    {
        ll a = Q.front().first.first;
        ll b = Q.front().first.second;
        ll c = Q.front().second;
        Q.pop();
 
        if (a == b && b == c && a == c)
        {
            Can_Answer = true;
            break;
        }
 
        ll Tmp_A, Tmp_B, Tmp_C;
 
        if (a < b)
        {
            Tmp_B = b - a;
            Tmp_A = a + a;
            Tmp_C = c;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
 
        if (a > b)
        {
            Tmp_A = a - b;
            Tmp_B = b + b;
            Tmp_C = c;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
 
        if (a < c)
        {
            Tmp_C = c - a;
            Tmp_A = a + a;
            Tmp_B = b;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
 
        if (a > c)
        {
            Tmp_A = a - c;
            Tmp_C = c + c;
            Tmp_B = b;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
 
        if (b < c)
        {
            Tmp_C = c - b;
            Tmp_B = b + b;
            Tmp_A = a;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
 
        if (b > c)
        {
            Tmp_B = b - c;
            Tmp_C = c + c;
            Tmp_A = a;
            if (Visit.find(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C)) == Visit.end())
            {
                Visit.insert(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
                Q.push(make_pair(make_pair(Tmp_A, Tmp_B), Tmp_C));
            }
        }
    }    
 
    if (Can_Answer == truecout << 1 << endl;
    else cout << 0 << 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









'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글

[ 백준 1062 ] 가르침 (C++)  (4) 2019.02.04
[ 백준 15558 ] 점프 게임 (C++)  (2) 2019.02.03
[ 백준 1339 ] 단어수학 (C++)  (0) 2019.02.02
[ 백준 1965 ] 상자넣기 (C++)  (0) 2019.02.02
[ 백준 1063 ] 킹 (C++)  (2) 2019.02.02

+ Recent posts