문제가 길어서 링크로 대체하겠다.
특별한 알고리즘 없이 톱니바퀴 4개가 회전하는 조건을 고려해서
회전을 구현하면 된다.
특별히 어려운 것은 없는 문제이다.
문제풀이
톱니바퀴에 대한 조건들은 다음과 같이 정리할 수 있다.
- 톱니바퀴는 1번부터 4번까지 총 4개가 있다.
- 톱니바퀴는 총 8개의 극이 있는데, N극 혹은 S극이다.
- 하나의 톱니바퀴가 회전할 때, 맞물린 톱니바퀴들과 맞닿은 극이 서로 다른 극이라면 맞물린 톱니바퀴를 회전하고, 서로 같은 극끼리 있다면 맞물린 톱니바퀴는 회전하지 않는다.
- 회전은 시계방향 혹은 반시계방향으로 가능하다.
조건은 위와 같은데, 3번째 조건을 구현하기가 어렵다. 예시를 들어서 조건을 따져서 풀어야 한다.
0 | 0 | 0 | |||||||||||||
7 | 1 | 7 | 1 | 7 | 1 | ||||||||||
6 | 2 | 6 | 2 | 6 | 2 | ... | |||||||||
5 | 3 | 5 | 3 | 5 | 3 | ||||||||||
4 | 4 | 4 |
(공간상 4번 톱니바퀴는 그리지 못했다. 그러나 이 그림만으로도 충분하다.)
첫번째 검은색 다이아몬드 모양이 1번 톱니바퀴,
두번째 파란색 다이아몬드 모양이 2번 톱니바퀴,
세번째 초록색 다이아몬드 모양이 3번 톱니바퀴이다.(4번 톱니바퀴도 있지만 생략됐다.)
만일 2번 톱니바퀴가 회전한다고 한다면 고려해야 할 사항은 다음과 같다.
- 2번 톱니바퀴의 왼쪽인 1번 톱니바퀴의 [2]극과 2번 톱니바퀴의 [6]극을 확인하고, 같다면 1번 톱니바퀴는 회전하지 않지만, 다르다면 1번 톱니바퀴도 회전시킨다.
- 2번 톱니바퀴의 오른쪽인 3번 톱니바퀴의 [6]극과 2번 톱니바퀴의 [2]극을 확인하고, 같다면 3번 톱니바퀴는 회전하지 않지만, 다르다면 3번 톱니바퀴도 회전시킨다.
- 만일 좌, 우측에 톱니바퀴가 회전한다면 좌, 우측에 맞물린 톱니바퀴도 회전하는 조건인지 확인한다.
즉, 현재 회전할 톱니바퀴의 좌측 톱니바퀴가 회전하는지 확인할 때는
- 현재 톱니바퀴[6] == 좌측 톱니바퀴[2] ? 를 고려한다.
그리고 현재 회전활 톱니바퀴의 우측 톱니바퀴가 회전하는지 확인할 때는
- 현재 톱니바퀴[2] == 우측 톱니바퀴[6] ? 를 고려한다.
그리고 맞물린 톱니바퀴가 회전한다면 해당 톱니바퀴에 맞물린 톱니바퀴들도 회전하는지 고려해주어야 한다.
위 조건들을 코드로 구현하면 된다.
먼저 memset() 메서드를 사용하기 위해 cstring STL을 사용했다.
- gear 배열 : 각 톱니바퀴의 극 8개를 저장할 배열.
- isSpin 배열 : 각 idx번의 톱니바퀴가 회전할지 안할지를 저장하는 배열. 매 톱니바퀴를 회전할 때마다 false로 초기화해주고 시작한다.
- gearSpinDirection 배열 : 만일 회전할 경우, 해당 톱니바퀴가 어디 방향으로 회전하는지 저장할 배열
- spinCnt : 회전시킬 횟수
- spinGearNum, spinDirection : 어떤 톱니바퀴를 어디 방향으로 회전시킬지 입력받는 변수
- answer : 출력할 정답.
톱니바퀴를 회전시키는 메서드이다. 시계방향 혹은 반시계방향으로 회전한다.
반시계방향은 그냥 그 다음값을 넣는 것이기 때문에, 순차적으로 진행해주면된다.
시계방향은 이전 값을 넣은 것이므로, 넣기 전에 저장하고 넣어야 한다.
이 부분을 고려하지 못해서 테스트 케이스가 하나 이상하게 나왔었다.
좌, 우 맞물린 톱니바퀴의 번호를 구하고, 맞물린 톱니바퀴가 회전할 방향을 초기화해준다.
좌측 톱니바퀴가 회전하는 조건은 다음과 같다.
- 번호가 1보다 크거나 같고
- 회전하는 조건이 아니며,(이미 회전하는 경우를 빼줘야 무한루프에 돌지 않게된다.)
- 현재 톱니바퀴의 6번째 극과 좌측 톱니바퀴의 2번째 극이 같다.
우측 톱니바퀴가 회전하는 조건은 다음과 같다.
- 번호가 4보다 작거나 같고
- 회전하는 조건이 아니며,(이미 회전하는 경우를 빼줘야 무한루프에 돌지 않게된다.)
- 현재 톱니바퀴의 2번째 극과 우측 톱니바퀴의 6번째 극이 같다.
회전하는 경우 회전한다고 저장한 후, 방향을 저장하고, 해당 톱니바퀴에 맞물린 톱니바퀴들도 고려한다.
메인함수에서는 처음에 톱니바퀴들의 숫자가 모두 붙어서 주어지므로, 문자열로 입력받아서 넣어준다.
그리고 회전하는 횟수를 입력받는다.
그리고 각 회전마다, 해당 idx번호의 톱니바퀴가 회전하는지를 저장해두는 isSpin 배열을 false로 초기화시켜놓는다.
후에 이번에 회전시킬 톱니바퀴 번호와 방향을 입력받고,
checkSpin 메서드를 실행시킨다.
checkSpin이 모두 종료되면 isSpin 배열을 1번부터 4번까지돌면서,
각 번호가 이번에 회전을 하는지 고려한 후 회전한다면 방향에 맞게 회전한다.
마지막으로 각 톱니바퀴의 12시 방향의 요소들이 S극이라면 answer변수에 해당하는 값만큼 더해주고 출력해준다.
골드5 구현문제 치고는 쉽게 맞출 수 있었던 문제였다.
코드는 위에서 확인이 가능하다.
'알고리즘 > Baekjoon' 카테고리의 다른 글
[C++] 백준 10819번 차이를 최대로 (0) | 2021.08.30 |
---|---|
[C++] 백준 1074번 Z (0) | 2021.08.29 |
[C++] 9020번 골드바흐의 추측 (0) | 2021.08.27 |
[C++] 백준 16236번 아기 상어 (0) | 2021.08.26 |
[C++] 백준 11048번 이동하기 (0) | 2021.08.26 |