문제 링크
https://programmers.co.kr/learn/courses/30/lessons/84021
코딩테스트 연습 - 퍼즐 조각 채우기
[[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0
programmers.co.kr
풀이
1. 퍼즐 별 모양 구하기
- find_puzzle 함수 : bfs로 퍼즐 모양 구하기
- trans_puz 함수 : 퍼즐의 index 변경하기
예를 들어,
위 그림의 5번은 [ [1], [1] ] 표현하고, 1번은 [ [0,1], [1,1], [0,1] ] 처럼 표현
2. 퍼즐 별로 회전 시켜가며 game_board에 채워지는지 확인, 채워진다면 빈공간 존재하는지 확인
- ratate 함수 : 배열 90도 회전
- check 함수 : game_board 에 퍼즐을 끼워가며 채워지는지 확인
- is_empty 함수 : 퍼즐을 끼운 board에 내부 빈공간이 존재하는지 확인
3. 가능하다면 퍼즐로 채울 수 있는 개수 answer에 더하기
from collections import deque
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
# 90도 회전
def rotate(board):
n = len(board)
m = len(board[0])
tmp = [ [0] * n for _ in range(m) ]
for i in range(n):
for j in range(m):
tmp[j][n-1-i] = board[i][j]
return tmp
# 퍼즐 위치 구하기
def find_puzzle(board, a, b, visited):
puzzle = []
visited[a][b] = True
n = len(board)
q = deque()
q.append((a,b))
# bfs
while q :
x, y = q.popleft()
puzzle.append((x,y))
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < n and 0 <= ny < n and board[nx][ny] == 1 and not visited[nx][ny]:
visited[nx][ny] = True
q.append((nx,ny))
return puzzle
# 퍼즐 index 변경
def trans_puz(puz):
# 세로 최대, 최소 index
max_x, min_x = -1, int(1e9)
# 가로 최대, 최소 index
max_y, min_y = -1, int(1e9)
for i in range(len(puz)):
x, y = puz[i]
max_x = max(max_x, x)
min_x = min(min_x, x)
max_y = max(max_y, y)
min_y = min(min_y, y)
# 세로 길이
len_x = max_x - min_x + 1
# 가로 길이
len_y = max_y - min_y + 1
trans = [ [0] *len_y for _ in range(len_x)]
for i in puz :
x = i[0] - min_x
y = i[1] - min_y
trans[x][y] = 1
return trans
# 채워지는지 확인
def check(puz, board):
n = len(board)
col = len(puz)
row = len(puz[0])
for i in range(n-col+1):
for j in range(n-row+1):
result = True
for x in range(col):
for y in range(row):
# 퍼즐 끼우기
board[x+i][y+j] += puz[x][y]
# 채워질 수 없으면
if board[i+x][j+y] != 1 :
result = False
# 내부 빈공간이 존재하면
if is_empty(board, puz, i, j):
result = False
if result :
return True
else:
# 퍼즐 제거
for x in range(col):
for y in range(row):
board[x+i][y+j] -= puz[x][y]
return False
# 빈공간 존재하는지 확인
def is_empty(board,puz,i,j):
n = len(board)
col = len(puz)
row = len(puz[0])
for x in range(col):
for y in range(row):
if puz[x][y] == 1 :
for z in range(4):
nx = x + dx[z] + i
ny = y + dy[z] + j
if 0<=nx <n and 0<=ny < n and board[nx][ny] != 1 :
return True
return False
def solution(game_board, table):
answer = 0
n = len(game_board)
visited = [ [False] * n for _ in range(n) ]
puzzle = []
puz_sum = []
# 퍼즐 모양 구하기
for i in range(n):
for j in range(n):
if table[i][j] and not visited[i][j]:
tmp = find_puzzle(table, i, j, visited)
puzzle.append(trans_puz(tmp))
# 퍼즐로 채울 수 있는 개수
puz_sum.append(len(tmp))
for i in range(len(puzzle)):
p = puzzle[i]
# 회전
for _ in range(4):
p = rotate(p)
if check(p, game_board):
answer += puz_sum[i]
break
return answer
- puz_sum에 퍼즐로 채울 수 있는 공간의 개수를 미리 구해놓지 않고 나중에 for문으로 구해주니깐 시간초과가 발생하였다.
'개발 > algorithm' 카테고리의 다른 글
[프로그래머스][level3] 길 찾기 게임 - python (0) | 2022.05.17 |
---|---|
[백준 12015번] 가장 긴 증가하는 부분 수열2 - python (0) | 2022.05.12 |
[백준 2294번] 동전2 - python (0) | 2022.05.06 |
[백준 11562번] 백양로 브레이크 - python (0) | 2022.05.06 |
[백준 1956번] 운동 - python (0) | 2022.05.06 |