Manduss life
[Python][구현] 메이즈 러너 - 코드트리 삼성 기출 본문
[문제]
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
[알고리즘]
- 참가자 이동
- exit의 y 좌표, 참가자의 y좌표 먼저 비교하여 위치 변경
- 그 후, exit의 x 좌표, 참가자의 x좌표 먼저 비교하여 위치 변경
- 이때, 조심해야할 것 before, after 데이터를 확실히 나누기. 변경된 값을 비교하는데 쓰일 수 있음
- 사람 존재하는지 여부 파악
- 존재하지 않는다면 종료
- 미로 회전
- 회전할 정사각형 영역 탐색
- 2x2 크기부터 NxN 크기 정사각형마다, 좌상단부터 탐색(완탐)
- 아래 코드 참고
- 정사각형 회전
- 아래 코드 참고
- 회전할 정사각형 영역 탐색
def set_square(exit):
is_exit = False
is_person = False
for n in range(2,N+1):
for i in range(N-n+1):
for j in range(N-n+1):
is_exit = False
is_person = False
for ii in range(n):
for jj in range(n):
if area_p[i+ii][j+jj] > 0:
is_person = True
elif area[i+ii][j+jj] == -1 :
is_exit = True
if is_exit and is_person :
break
if is_exit and is_person:
break
if is_exit and is_person:
break
return (i, j), (i+n-1, j+n-1)
def rotate_matrix(a):
a_ = [[0 for _ in range(len(a))] for _ in range(len(a))]
length = len(a)
for i in range(length):
for j in range(length):
a_[j][length-1-i] = a[i][j]
return a_
[느낀점 / 깨달은 점]
- 구현문제는 웬만하면 완탐으로 접근하자. (까다로운 예외처리가 필요한 나만의 알고리즘을 사용하지 말고)
- 처음에 회전시킬 정사각형 탐색하는 함수를 구현할 때, exit 기준으로 bfs로 가까운 사람을 찾고, 가로 세로 중 긴 변을 찾아서.. 어찌구저찌구 로 구현하였는데, 너무 복잡하고, 디버깅할 때도 불편했다. 디버깅 포기하고 다른 사람 코드 보니 정사각형 크기 순으로 완탐으로 구현했더라. 다시 구현하니 훨씬 코드도 간략했음. (비록 for문이 5개지만..)
- 상태 변화가 있을 경우, before, after 상태를 각각 저장하자.
- 초반에 따로 저장을 안하고 구현하여서, 사람 옮길 때, 이전 사람이 이동한 후의 상태를 가지고 다음 사람 이동에 적용돼버림..
- 꼭 before, after 따로 저장하자.
- 그리고 벽, 사람 등 matrix 내 고려사항이 여러개라면, 서로 다른 Matrix로 저장하자.
- 초반에 벽의 내구도가 담긴 배열, 사람의 인원수 배열을 같은 배열로 사용하였다. 벽의 내구도는 0~9, 사람의 인원은 10부터 시작. 1명이면 11, 2명이면 12..
- 이렇게 되면 사람을 옮길 때 계산이 복잡해진다. 0부터 시작하는 각각 다른 배열을 사용하도록 하자.
- 처음 주어질 때부터 사람이 겹치게 주어진다는 것을 생각지 못했다. 다양한 경우의 수를 생각해야 한다. ㅎㅁㅇ.
- 생각보다 회전 배열 구현이 간단하네?? 이건 빠르게 구현했다. 예전에 구현했을 때는 저 코드보다 길었는데.. 암튼 이건 만족.
- 내가 구현한 move_people() 코드는 너무 맘에 안들지만, 통과니까 뭐!
[코드]
import sys
from collections import deque
def print_2d(a):
for i in a:
for j in i:
print(j, end=' ')
print()
print('=====')
def print_2d2(a, b):
for i, j in zip(a, b):
for ii, jj in zip(i, j):
print(ii+ 10*jj, end=' ')
print()
print('=====')
def find_people_and_exit():
exit = ()
people = []
for i in range(N):
for j in range(N):
if area_p[i][j] > 0 :
people.append([i, j, area_p[i][j]])
if area[i][j] == -1 :
exit = (i, j)
return people, exit
def move_people(people, exit):
global final_move_length
print('before final_move_length', final_move_length)
ei, ej = exit
p_after = people[:]
for n, p in enumerate(people) :
is_move = False
is_skip = False
pi, pj, n_p = p
pii, pjj, _ = p
if pi > ei :
pii = pi -1
elif pi < ei :
pii = pi +1
else :
is_skip = True
if not is_skip :
# if not (pii < 0 or pjj < 0 or pii >=N or pjj >=N or 0 < area[pii][pjj] < 10) :
if pii >= 0 and pjj >= 0 and pii < N and pjj < N:
if area[pii][pjj] == -1 : ## 출구일 때
p_after[n][0] = -1
p_after[n][1] = -1
final_move_length += n_p
continue
elif area_p[pii][pjj] > 0: ## 사람이 있을 때
p_after[n][0] = pii
p_after[n][1] = pjj
# area[pii][pjj] += n_p
# area[pi][pj] = 0
final_move_length += n_p
continue
elif area[pii][pjj] == 0 and area_p[pii][pjj] == 0: ## 아무도 없을 때
p_after[n][0] = pii
p_after[n][1] = pjj
# area[pii][pjj] = 10+n_p
# area[pi][pj] = 0
final_move_length += n_p
continue
pii, pjj, _ = p
if pj > ej :
pjj = pj -1
elif pj < ej :
pjj = pj + 1
else :
continue
if pii < 0 or pjj < 0 or pii >=N or pjj >=N or 0 < area[pii][pjj] < 10 :
continue
final_move_length += n_p
if area[pii][pjj] == -1 : ## 출구일 때
p_after[n][0] = -1
p_after[n][1] = -1
# area[pi][pj] = 0
elif area_p[pii][pjj] > 0: ## 사람이 있을 때
p_after[n][0] = pii
p_after[n][1] = pjj
# area[pii][pjj] += n_p
# area[pi][pj] = 0
elif area[pii][pjj] == 0 and area_p[pii][pjj] == 0: ## 아무도 없을 때
p_after[n][0] = pii
p_after[n][1] = pjj
# area[pii][pjj] = 10+n_p
# area[pi][pj] = 0
area_p_after = [[0 for _ in range(N)] for _ in range(N)]
for p in p_after:
i, j, np = p
if i == -1 and j == -1 :
continue
area_p_after[i][j] += np
return area_p_after
def set_square(exit):
is_exit = False
is_person = False
for n in range(2,N+1):
for i in range(N-n+1):
for j in range(N-n+1):
is_exit = False
is_person = False
for ii in range(n):
for jj in range(n):
if area_p[i+ii][j+jj] > 0:
is_person = True
elif area[i+ii][j+jj] == -1 :
is_exit = True
if is_exit and is_person :
break
if is_exit and is_person:
break
if is_exit and is_person:
break
return (i, j), (i+n-1, j+n-1)
def rotate_matrix(a):
a_ = [[0 for _ in range(len(a))] for _ in range(len(a))]
length = len(a)
for i in range(length):
for j in range(length):
a_[j][length-1-i] = a[i][j]
return a_
def rotate_square(lu, rb):
import copy
lui, luj = lu
rbi, rbj = rb
temp_area = [a[luj:rbj+1] for a in area[lui:rbi+1]]
temp_area_p = [a[luj:rbj+1] for a in area_p[lui:rbi+1]]
temp_area = rotate_matrix(temp_area)
temp_area_p = rotate_matrix(temp_area_p)
for i in range(len(temp_area)) :
for j in range(len(temp_area)) :
if 0 < temp_area[i][j] < 10 :
area[i+lui][j+luj] = temp_area[i][j] -1
else :
area[i+lui][j+luj] = temp_area[i][j]
area_p[i + lui][j + luj] = temp_area_p[i][j]
del temp_area
def rotate_miro(exit) :
lu, rb = set_square(exit)
rotate_square(lu, rb)
dy = [-1, 0, 1, 0]
dx = [0, -1, 0, 1]
N, M , K = map(int, input().split())
area = [list(map(int, input().split())) for _ in range(N)]
area_p = [[0 for _ in range(N)] for _ in range(N)]
for _ in range(M) :
i, j = map(int, input().split())
area_p[i-1][j-1] += 1
exit = list(map(int, input().split()))
final_move_length = 0
area[exit[0]-1][exit[1]-1] = -1
for k in range(K):
people, exit = find_people_and_exit()
if len(people) == 0:
break
area_p = move_people(people, exit)
people, exit = find_people_and_exit()
if len(people) == 0:
break
rotate_miro(exit)
print(final_move_length)
_, exit = find_people_and_exit()
print(exit[0]+1, exit[1]+1)
'전산 > Algorithm' 카테고리의 다른 글
[Python][구현] 술래 잡기 - 코드트리 (1) | 2024.06.09 |
---|---|
[Python][구현/BFS] 코드트리 빵 - 코드트리 삼성 기출 (0) | 2023.12.08 |
[Python][DP] 등굣길 - 프로그래머스 (0) | 2023.08.06 |
[Python] 1차 캐시 - 프로그래머스 / 2018 KAKAO BLIND RECRUITMENT (0) | 2023.07.31 |
[Python][Greedy?] 단속카메라 - 프로그래머스 Lv.3 (0) | 2023.05.07 |
Comments