티스토리 뷰

#문제

https://www.acmicpc.net/problem/12906


#풀이

은근 시간이 많이 걸렸던 문제입니다.


딱 문제를 보자마자 모든 경우의 수를 해봐야겠다! 라는 생각이 들었습니다.

저는 모든 경우의 수를 돌릴 때에는 대부분 DFS로 했기 때문에 해당 문제도 그렇게 접근하려 했습니다.

하지만, 원판을 내 마음대로 뽑을 수 있는 것이 아니라 무조건 맨 위에있는 원판 만 움직일 수 있으므로 풀이가 쉽지 않았습니다.


결국... 구글링... :)

풀이가 많이 있지도 않았습니다... 아직 많이 풀어보지 않은 문제라 그런가 봅니다...

딱 한가지 풀이가 있었는데 BFS를 이용하였습니다.(참고 사이트)


BFS로 모든 경우의 수를 돌리는 것이 이해가 더 잘 오기에 BFS로 풀게 되었습니다.


큐에 넣을 때는 현재 탑들의 상황과 해당 상황이 오기까지 원판을 몇번 옮겼는가를 저장해 둡니다.

큐에 넣었을 때 중복되는 상황들을 막기 위해 Set을 사용하여 중복을 막아 줍니다.

이 후 큐에서 뺄 때마다 해당 상황이 끝인가를 판단해주고, 만약 끝이라면 같이 저장한 움직임의 횟수를 출력합니다.


이와 비슷한 문제들이 있습니다.

같이 풀어보시면 좋을듯 합니다!

[돌 그룹] : https://www.acmicpc.net/problem/12886

[4 연산] :  https://www.acmicpc.net/problem/14395


#코드

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
#include <iostream>
#include <string>
#include <queue>
#include <set>
using namespace std;
 
struct Hanoi{
    string sticks[3];
    int cnt;
};
 
bool operator<(const Hanoi& h1, const Hanoi& h2){
    if(h1.sticks[0== h2.sticks[0]){
        if(h1.sticks[1== h2.sticks[1]){
            return h1.sticks[2< h2.sticks[2];
        }
        return h1.sticks[1< h2.sticks[1];
    }
    return h1.sticks[0< h2.sticks[0];
}
 
Hanoi hanoi;
set<Hanoi> visit;
 
bool checkingFinish(string A, string B, string C){
    for(int i = 0; i < A.size(); i++){
        if(A[i] != 'A'return false;
    }
    for(int i = 0; i < B.size(); i++){
        if(B[i] != 'B'return false;
    }
    for(int i = 0; i < C.size(); i++){
        if(C[i] != 'C'return false;
    }
    return true;
}
 
void playTheHanoi(){
    queue<Hanoi> q;
    q.push(hanoi);
    visit.insert(hanoi);
    while(!q.empty()){
        string stickA = q.front().sticks[0];
        string stickB = q.front().sticks[1];
        string stickC = q.front().sticks[2];
        int cnt = q.front().cnt;
        q.pop();
    
        //들어온 값을 확인하여 끝났는지 확인
        if(checkingFinish(stickA, stickB, stickC)){
            cout << cnt << endl;
            return;
        }
        
        //A에서 다른 막대기로
        if(!stickA.empty()){
            //맨 위, 즉 맨 마지막 문자를 빼서 옮긴다.
            string nextStickA = stickA.substr(0,stickA.size()-1);
            char movingPlate = stickA[stickA.size()-1];
            
            Hanoi h;
            h.cnt = cnt + 1;
            // A -> B
            h.sticks[0= nextStickA;
            h.sticks[1= stickB + movingPlate;
            h.sticks[2= stickC;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
            // A -> C
            h.sticks[0= nextStickA;
            h.sticks[1= stickB;
            h.sticks[2= stickC + movingPlate;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
        }
        //B에서 다른 막대기로
        if(!stickB.empty()){
            //맨 위, 즉 맨 마지막 문자를 빼서 옮긴다.
            string nextStickB = stickB.substr(0,stickB.size()-1);
            char movingPlate = stickB[stickB.size()-1];
            
            Hanoi h;
            h.cnt = cnt + 1;
            // B -> A
            h.sticks[0= stickA + movingPlate;
            h.sticks[1= nextStickB;
            h.sticks[2= stickC;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
            // B -> C
            h.sticks[0= stickA;
            h.sticks[1= nextStickB;
            h.sticks[2= stickC + movingPlate;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
        }
        //C에서 다른 막대기로
        if(!stickC.empty()){
            //맨 위, 즉 맨 마지막 문자를 빼서 옮긴다.
            string nextStickC = stickC.substr(0,stickC.size()-1);
            char movingPlate = stickC[stickC.size()-1];
            
            Hanoi h;
            h.cnt = cnt + 1;
            // C -> A
            h.sticks[0= stickA + movingPlate;
            h.sticks[1= stickB;
            h.sticks[2= nextStickC;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
            // C -> B
            h.sticks[0= stickA;
            h.sticks[1= stickB + movingPlate;
            h.sticks[2= nextStickC;
            if(visit.find(h) == visit.end()){
                q.push(h);
                visit.insert(h);
            }
        }
    }
}
 
int main(){
    for(int i = 0; i < 3; i++){
        int num;
        cin >> num;
        if(num != 0)
            cin >> hanoi.sticks[i];
    }
    hanoi.cnt = 0;
    playTheHanoi();
    return 0;
}
 
cs


'알고리즘 문제 풀이 > BOJ' 카테고리의 다른 글

[BOJ 11048] 이동하기  (0) 2019.03.05
[BOJ 3197] 백조의 호수  (2) 2019.02.25
[BOJ 2234] 성곽  (0) 2019.02.24
[BOJ 14442] 벽 부수고 이동하기 2  (0) 2019.02.24
[BOJ 5213] 과외맨  (1) 2019.02.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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
글 보관함