문제 링크
- http://icpc.me/16985
문제 출처
- 2019 3/1 코딩테스트 특강 ( /Ba+rking/님 )
사용 알고리즘
- BFS
- Brute Force
풀이
3/1에 서울대학교에서 진행된 코딩테스트 특강 모의고사 문제입니다.
문제는 크게 3가지의 부분 문제로 분할됩니다.
- 판 회전 (rotating)
- 판 쌓기 (stacking)
- 길 찾기 (bfs)
한 가지 당연한듯 당연하지 않은듯한 사실 하나를 알면 문제를 푸는데 더 수월해집니다.
Lemma 1. 입구와 출구는 (0, 0, 0), (4, 4, 4)로 고정해도 무방하다.
proof ) 입구와 출구가 (0, 0, 0)과 (4, 4, 4)가 아닌 다른 곳이라고 가정을 하자. 큐브 전체를 적절히 돌리면 (0, 0, 0), (4, 4, 4)로 바꿀 수 있다.
이제, 한 단계씩 문제를 풀어봅시다.
1. 판 회전 (rotating)
00 01 02 03 04
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
40 41 42 43 44
를
*
40 30 20 10 00
41 31 21 11 01
42 32 22 12 02
43 33 23 13 03
44 34 24 14 04
*
로 변환하는 과정을 생각해봅시다. 이는 (i, j)가 (j, 5-1-i)로 바뀐다는 사실을 쉽게 알 수 있습니다.
0 ≤ rot ≤ 3인 자연수 rot에 대해 입력받은 5개의 판을 모두 rot번 회전시킨 결과를 rotated[rot][i][j][k]에 저장해줍시다. 상세한 구현은 아래 코드에서 rotating함수 부분을 참고해주시기 바랍니다.
2. 판 쌓기 (stacking)
이 부분 문제에서는 permutation과 bitmask기법을 사용하여 쉽게 해결할 수 있습니다.
stackingOrder[] = {0, 1, 2, 3, 4} 배열에 대한 permutation을 모두 구해서 해당 순서대로 판을 쌓아주면 되기는 합니다만, 회전 처리가 남아있습니다.
5개의 판은 각각 0~3번 회전할 수 있고, 이진수로 나타내면 {00, 01, 10, 11}입니다. 총 10개의 비트를 만든 뒤, 2개씩 쪼개서 판의 회전 횟수로 나타낼 수 있습니다.
ㅇ
예를 들어 00 00 00 00 00
은 5개의 판 모두 0번 회전을 한 것이고,
10 00 00 00 00
은 첫 번째 판은 2번, 나머지는 0번을 회전한 것을 의미합니다.
0부터 (210-1)까지 순회하면 판이 회전하는 모든 경우를 탐색할 수 있습니다. 상세한 구현은 아래 코드에서 stacking함수 부분을 참고해주시기 바랍니다.
3. 길 찾기 (bfs)
이 부분은 전형적인 bfs구현입니다.
1 |
|
를 적절히 활용하면 bfs를 쉽게 구현할 수 있습니다.
추천 문제
KOI2013 지역 본선 초등부 3번 토마토 (링크)
KOI2000 초등부 3번 치즈 (링크)
두 문제 maze문제보다 모두 쉽긴 합니다만, bfs를 연습하는데는 좋은 문제라고 생각합니다.
전체 코드
1 |
|