| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 부분수열의 합2
- 구현
- 2247
- 코테
- 모두의 꿈
- lgb
- 다이나믹 프로그래밍
- python
- 실질적 약수
- 스펨메일 분류
- 코딩테스트
- 정답코드
- 17070
- 27448
- 파이썬
- dfs
- dp
- 힙 정렬
- 샤논 엔트로피
- T tree
- 딥러닝
- C
- populating next right pointers in each node
- BFS
- 아니메컵
- 코딩
- 코복장
- 백준
- ps
- 정렬
- Today
- Total
코딩복습장
백준: 14891번 톱니바퀴 본문
문제
총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴가 1번, 그 오른쪽은 2번, 그 오른쪽은 3번, 가장 오른쪽 톱니바퀴는 4번이다.

이때, 톱니바퀴를 총 K번 회전시키려고 한다. 톱니바퀴의 회전은 한 칸을 기준으로 한다. 회전은 시계 방향과 반시계 방향이 있고, 아래 그림과 같이 회전한다.


톱니바퀴를 회전시키려면, 회전시킬 톱니바퀴와 회전시킬 방향을 결정해야 한다. 톱니바퀴가 회전할 때, 서로 맞닿은 극에 따라서 옆에 있는 톱니바퀴를 회전시킬 수도 있고, 회전시키지 않을 수도 있다. 톱니바퀴 A를 회전할 때, 그 옆에 있는 톱니바퀴 B와 서로 맞닿은 톱니의 극이 다르다면, B는 A가 회전한 방향과 반대방향으로 회전하게 된다. 예를 들어, 아래와 같은 경우를 살펴보자.

두 톱니바퀴의 맞닿은 부분은 초록색 점선으로 묶여있는 부분이다. 여기서, 3번 톱니바퀴를 반시계 방향으로 회전했다면, 4번 톱니바퀴는 시계 방향으로 회전하게 된다. 2번 톱니바퀴는 맞닿은 부분이 S극으로 서로 같기 때문에, 회전하지 않게 되고, 1번 톱니바퀴는 2번이 회전하지 않았기 때문에, 회전하지 않게 된다. 따라서, 아래 그림과 같은 모양을 만들게 된다.

위와 같은 상태에서 1번 톱니바퀴를 시계 방향으로 회전시키면, 2번 톱니바퀴가 반시계 방향으로 회전하게 되고, 2번이 회전하기 때문에, 3번도 동시에 시계 방향으로 회전하게 된다. 4번은 3번이 회전하지만, 맞닿은 극이 같기 때문에 회전하지 않는다. 따라서, 아래와 같은 상태가 된다.

톱니바퀴의 초기 상태와 톱니바퀴를 회전시킨 방법이 주어졌을 때, 최종 톱니바퀴의 상태를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터 시계방향 순서대로 주어진다. N극은 0, S극은 1로 나타나있다.
다섯째 줄에는 회전 횟수 K(1 ≤ K ≤ 100)가 주어진다. 다음 K개 줄에는 회전시킨 방법이 순서대로 주어진다. 각 방법은 두 개의 정수로 이루어져 있고, 첫 번째 정수는 회전시킨 톱니바퀴의 번호, 두 번째 정수는 방향이다. 방향이 1인 경우는 시계 방향이고, -1인 경우는 반시계 방향이다.
출력
총 K번 회전시킨 이후에 네 톱니바퀴의 점수의 합을 출력한다. 점수란 다음과 같이 계산한다.
- 1번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 1점
- 2번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 2점
- 3번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 4점
- 4번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 8점
예제 입력 1 복사
10101111
01111101
11001110
00000010
2
3 -1
1 1
예제 출력 1 복사
7
예제 입력 2 복사
11111111
11111111
11111111
11111111
3
1 1
2 1
3 1
예제 출력 2 복사
15
예제 입력 3 복사
10001011
10000011
01011011
00111101
5
1 1
2 1
3 1
4 1
1 -1
예제 출력 3 복사
6
예제 입력 4 복사
10010011
01010011
11100011
01010101
8
1 1
2 1
3 1
4 1
1 -1
2 -1
3 -1
4 -1
예제 출력 4 복사
5
이 문제는 단순 구현문제 이지만, 구현해야될 요소가 엄청나게 많은 문제인 것 같다.
톱니바퀴가 돌아가는 조건이 복잡해 실수하기 쉬운 문제인 것 같다.
풀이시간은 1시간 26분...
설명시작~

우선 나는 톱니바퀴가 돌아가는 조건을 살펴봤다.
1. NS가 붙어있으면 돌아가는데, 이 조건을 확인하는 함수를 두고 싶었다.

이 상황에서는 [1, 0, 0] 반환하는 함수이다. (영향을 받는 연결부위를 1로 아닌 부분을 0으로)
2. 그리고 이 조건을 받아서 돌아가는 톱니바퀴에 영향을 받는 톱니바퀴도 구하고 싶었다. (+ 어느방향으로 돌아가는지)
이 부분은 돌아가는 체인 부분에서 영향을 받는 체인이 있는지 양 옆으로 판단을 해야한다. 나는 이것을 그래프 탐색으로 보고 dfs를 통해 탐색했다. (단순 조건문을 사용하기엔 코드가 너무 길어질 것이라 판단 + 톱니가 4개라 탐색이 금방 끝날 것이라 판단)

이렇게 탐색을 하다 connection이 0인 부분이라면 queue에 등록하지 않는 방식을 사용
만약 visited 한 톱니라면 queue에 추가 안함.
connection있고 visited x라면 queue에 추가.
연결이 있을 때, visited에 [1, 돌아가는 방향] 등록 ( 돌아가는 방향은 이전 체인의 방향 * -1 이다.->반대방향으로 돌기 때문)
1, 2를 함수로 만들어서 돌아가는 톱니바퀴에 영향을 받는 톱니바퀴와 영향받은 톱니바퀴가 어느 방향으로 돌아가는지도 반환
이후에 deque를 사용하여 돌아가는 톱니바퀴를 구현했다. (deque가 양방향 큐이기 때문에 구현하기 쉬울 것이라 판단)

구현코드
from collections import deque
LMP, RMP = 6, 2
chain = []
for _ in range(4):
chain.append(deque(map(int, input())))
n = int(input())
command = []
for _ in range(n):
command.append(list(map(int, input().split())))
# N: 0, S: 1
# print(chain)
# print(command)
def chain_info(): # 3개의 연결부위 정보 반환
res = []
for i in range(3):
if chain[i][RMP] != chain[i+1][LMP]:
res.append(1)
else: res.append(0)
return res
def change_connection(info, c, d): # 변화하는 체인의 번호 리스트 반환
dx = [1, -1]
queue = deque()
need_visited = [0, 0, 0, 0]
queue.append([c, d])
while queue:
chain, dir = queue.pop()
need_visited[chain] = dir
for i in range(2):
cn = chain + dx[i]
if -1 < cn < 4 and need_visited[cn] == 0:
if i == 0 and info[chain] == 1:
queue.append([cn, dir * (-1)])
elif i == 1 and info[cn] == 1:
queue.append([cn, dir * (-1)])
return need_visited
def rotate_chain(c, d):
info = chain_info()
#print(f'info:{info}')
infect = change_connection(info, c, d)
#print(f'infect{infect}')
for idx in range(4):
if infect[idx] == 0:
continue
else:
if infect[idx] == -1:
temp = chain[idx].popleft()
chain[idx].append(temp)
elif infect[idx] == 1:
temp = chain[idx].pop()
chain[idx].appendleft(temp)
for c, d in command:
rotate_chain(c-1, d)
# print(chain)
res = 0
if chain[0][0] == 1: res += 1
if chain[1][0] == 1: res += 2
if chain[2][0] == 1: res += 4
if chain[3][0] == 1: res += 8
print(res)'코딩 테스트 > python(파이썬)' 카테고리의 다른 글
| LeetCode: Array Partition (0) | 2025.06.09 |
|---|---|
| LeetCode: Remove Element (2) | 2025.06.07 |
| LeetCode: Longest Common Prefix (0) | 2025.06.03 |
| LeetCode: Valid Parentheses (0) | 2025.06.03 |
| LeetCode: Maximum Gap (0) | 2025.05.31 |