🔗 문제
14891번: 톱니바퀴
총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴
www.acmicpc.net
🖍 풀이
더 효율적인 방법이 있나 검색해봤는데 나처럼 푼 사람은 없는 것같아 뿌듯.. (하지만 있을 수도.. )
최대한 배열 복사하기가 싫어서 꼭지점 인덱스를 기준으로 풀었지만, 회전하고 나서 배열 변경해도 시간초과가 나지 않는다.
deque를 이용해서 풀어도 시간초과는 나지 않는다.
- n번 톱니바퀴를 d방향으로 회전 시킨다.
- n번 톱니바퀴를 기준으로 왼쪽은 [n][6] 과 [n-1][2]의 값을 비교한다.
- n번 톱니바퀴를 기준으로 오른쪽은 [n][2]와 [n+1][6]의 값을 비교한다.
- 각각 왼쪽, 오른쪽의 조건이 맞으면 방향따라 연쇄적으로 조건을 적용시킨다.
- 회전이 끝나면 톱니바퀴 값은 갱신해준다.
톱니바퀴의 회전 방향에 따라 인접 톱니바퀴의 극이 있는 방향이 다르기 때문에 따로 함수를 만들어 주었다.
void rotation(int num, int dir)
{
rotationRight(num, dir);
rotationLeft(num, dir);
pos[num] = (pos[num] + dir*-1 + 8) % 8;
}
왼쪽방향은 [n][6] 과 [n-1][2]의 값을 비교해야 한다.
pos[num]이 num번 톱니바퀴의 맨 위 꼭지점 인덱스를 저장해주었다.
원형큐처럼 size + pos[num] + 이동하려는 칸) % size 로 꼭지점을 기준으로 오른쪽, 왼쪽의 인덱스를 알 수 있다.
- 조건이 맞으면 연쇄적으로 그 방향 진행
- 진행이 끝난 후 꼭지점 갱신
void rotationLeft(int num, int dir)
{
if(num-1 == -1) return;
int now = (pos[num]+6) % 8; // 현재 톱니바퀴의 왼쪽 극성
int next = (pos[num-1]+2) % 8; // 현재 톱니바퀴 왼쪽에 있는 맞물리는 극성
if(gears[num][now] != gears[num-1][next]) // 회전하자.
{
rotationLeft(num-1, (dir*-1)); // 반대 방향으로 회전한다.
// 반대로 회전하기 떄문에 꼭지점 인덱스가 dir만큼 이동
pos[num-1] = (pos[num-1] + dir + 8) % 8;
}
}
주의사항
-1 (반시계방향)으로 회전하면 배열 인덱스의 꼭지점이 ‘증가’하기 때문에 d*-1 해준다.
반 시계방향 회전 전: 10111111 // 0의 인덱스 1
반 시계방향 회전 후: 01111111 // 0의 인덱스 2
// -1 방향으로 이동했을 때 배열 인덱스상으로는 -1*-1 = 1 이동했다.
while(K--)
{
std::cin >> num >> d;
rotation(num, d);
}
...
void rotation(int num, int dir)
{
rotationRight(num, dir);
rotationLeft(num, dir);
pos[num] = (pos[num] + dir*-1 + 8) % 8;
}
💾 소스
#include <iostream>
char gears[5][8];
int pos[5] = {0, };
void rotationRight(int num, int dir)
{
if(num+1 == 5) return;
int now = (pos[num]+2)%8;
int next = (pos[num+1]+6)%8;
if(gears[num][now] != gears[num+1][next])
{
rotationRight(num+1, (dir*-1));
pos[num+1] = (pos[num+1] + dir + 8) % 8;
}
}
void rotationLeft(int num, int dir)
{
if(num-1 == -1) return;
int now = (pos[num]+6) % 8;
int next = (pos[num-1]+2) % 8;
if(gears[num][now] != gears[num-1][next])
{
rotationLeft(num-1, (dir*-1));
pos[num-1] = (pos[num-1] + dir + 8) % 8;
}
}
void rotation(int num, int dir)
{
rotationRight(num, dir);
rotationLeft(num, dir);
pos[num] = (pos[num] + dir*-1 + 8) % 8;
}
int main()
{
int K, N, D;
for(int i=1; i<5; ++i)
{
for(int j=0; j<8; ++j)
{
std::cin >> gears[i][j];
}
}
std::cin >> K;
while(K--)
{
std::cin >> N >> D;
rotation(N, D);
}
int answer = 0;
for(int i=1; i<5; ++i)
{
if(gears[i][pos[i]]=='1')
answer += (1 << (i-1));
}
std::cout << answer;
return 0;
}