자료구조&알고리즘/프로그래머스
[프로그래머스] 131702번 고고학 최고의 발견 풀이 (Python)
고쩡이
2025. 4. 2. 14:36
https://school.programmers.co.kr/learn/courses/30/lessons/131702
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
이 문제를 완전탐색으로 푼다면 시간복잡도는 O(4**64)로, 완전탐색은 불가능하다.
시계를 하나 돌리면 주변까지 돌아가기 때문에, 아무데나 돌리면 안된다.
이 문제의 핵심은 맨 윗줄만 완전탐색을 하고 나머지는 앞의 줄에 종속적이란것이다. O(4**8)
이해를 돕기위해 비루하지만 PPT로 쉽게 나타내봤다...
이를 정리하면 다음과같다.
먼저 맨 윗줄에서 모든 누름 조합을 시도해본다.(완전 탐색)
윗줄이 결정되면 -> 2번째 줄은 1번째 줄을 맞추려고누르고
->3번째 줄은 2번째 줄을 맞추려고 누른다.
마지막 줄까지 갔을 때 다 12시 방향이면 성공이다.
그런 경우 중에서 가장 적은 누름 횟수를 정답으로 한다.
대략적인 코드 흐름은 아래와 같다.
for 모든 가능한 첫 줄 누르기 조합:
현재 퍼즐 상태 = 원본 복사
첫 줄을 누른다 (지정된 횟수만큼)
아래 줄부터는 위 칸을 맞추기 위해 강제적으로 누른다
마지막 줄이 전부 0이면 성공 → 최소 횟수 갱신
코드
from itertools import product
from copy import deepcopy
def solution(clockHands):
directions = [(-1,0),(1,0),(0,1),(0,-1),(0,0)]
N = len(clockHands)
answer = int(1e9)
# 첫 번째 줄의 모든 누름 조합 (0~3)
for first_row in product(range(4), repeat=N):
new_board = deepcopy(clockHands)
cnt = 0
# 첫 줄 누르기
for c, times in enumerate(first_row):
if times:
for dx, dy in directions:
nx, ny = 0 + dx, c + dy
if 0 <= nx < N and 0 <= ny < N:
new_board[nx][ny] = (new_board[nx][ny] + times) % 4
cnt += times # 조작횟수 누적
# 두 번째 줄부터는 위 줄 맞추기 위해 자동 누르기
for r in range(1, N):
for c in range(N):
times = (4 - new_board[r - 1][c]) % 4
if times:
for dx, dy in directions:
nx, ny = r + dx, c + dy
if 0 <= nx < N and 0 <= ny < N:
new_board[nx][ny] = (new_board[nx][ny] + times) % 4
cnt += times
# 마지막 줄이 모두 0인지 확인
if all(x == 0 for x in new_board[-1]):
answer = min(answer, cnt)
return answer