1. 문제
https://www.acmicpc.net/problem/19237
2. 풀이
삼성 SW 역량테스트 문제입니다. 풀이 순서는 아래와 같습니다.
- 이 문제는 상어가 move 하면서 주변 냄새를 남긴 곳들의 값이 1씩 감소합니다. 이러한 과정을 수행하기 위하여 함수로 나눴습니다.
- move(상어들을 이동시킴) : 가능한 갈 수 있는 곳 모두 체크 -> 주변에 빈 곳과 자신의 냄새가 있는 곳을 찾음 -> 주변에 빈 곳이 있으면 우선순위 높은거 선택. 없으면 냄새가 있는 곳에서 우선순위 높은거 선택.
- minus_smell(냄새 값들을 1씩 감소시킴)
- drop_smell(이동시킨 상어들의 위치에 냄새를 남김)
- 자료구조는 대부분 list를 사용했습니다. 상어들의 위치와 남은 시간은 map을 따로 생성하여 사용했습니다.
- shark_maps : 상어들의 위치
- smell_maps : 냄새를 남긴 상어와 남은 시간
삼성문제들의 특성으로 간단한 구조이지만 조건들이 많이 복잡합니다. index 관리를 매우 잘 해주어야 합니다(예를 들어, index는 0~N-1 이고 상어는 1~N을 사용하는 경우). 저도 index 관리를 잘 못해서 오답에 빠지는 경우가 많았습니다.
# 위, 아래, 왼쪽, 오른쪽
UP, DOWN, LEFT, RIGHT = [1, 2, 3, 4]
N, M, k = map(int, input().split())
shark_maps = [list(map(int, input().split())) for _ in range(N)]
shark_way = list(map(int, input().split()))
shark_priority = [[list(map(int, input().split())) for _ in range(4)] for __ in range(M)]
# 앞에는 상어, 뒤에는 남은 시간
smell_maps = [[[0, 0] for __ in range(N)] for _ in range(N)]
dr = [-1,1,0,0]
dc = [0,0,-1,1]
# 향기 남기기
def drop_smell():
for r in range(N):
for c in range(N):
if shark_maps[r][c] == 0:
continue
smell_maps[r][c] = [shark_maps[r][c], k]
# 향기 값 -1
def minus_smell():
for r in range(N):
for c in range(N):
if smell_maps[r][c][0] == 0:
continue
smell_maps[r][c] = [(smell_maps[r][c][0] if smell_maps[r][c][1]-1 != 0 else 0), smell_maps[r][c][1]-1]
# 이동하기
def move():
global shark_maps
sub_maps = [[[] for __ in range(N)] for _ in range(N)]
for r in range(N):
for c in range(N):
shark_num = shark_maps[r][c]
if shark_num == 0:
continue
# 다음 가능한 갈 수 있는 곳 모두 체크
empty = []
my_smell = []
for w_idx in range(1, 4+1):
next_row = r + dr[w_idx-1]
next_col = c + dc[w_idx-1]
if next_row < 0 or next_row >= N or next_col < 0 or next_col >= N:
continue
## 주변에 빈 곳 찾기
if smell_maps[next_row][next_col] == [0,0]:
empty.append(w_idx)
## 빈 곳이 없으면 자신의 냄새가 있는 곳
elif smell_maps[next_row][next_col][0] == shark_num:
my_smell.append(w_idx)
next_can = my_smell if len(empty) == 0 else empty
# 다음 갈 곳 확인
next = False
for w_idx in shark_priority[shark_num-1][shark_way[shark_num-1]-1]:
if next != False:
break
for n in next_can:
if w_idx == n:
next = w_idx
break
if next == False:
continue
next_row = r + dr[next-1]
next_col = c + dc[next-1]
sub_maps[next_row][next_col].append(shark_num)
shark_way[shark_num-1] = next
# 이동한 얘들 중 최소만 남기고 다음 맵으로 갱신
shark_maps = [[(min(sub_maps[r][c]) if len(sub_maps[r][c]) else 0) for c in range(N)] for r in range(N)]
# 이동하기 & 이전 요소들 다 1씩 감소
drop_smell()
t = 1
while t <= 1000:
move()
minus_smell()
drop_smell()
# 상어 수 세기
shark_num = 0
for r in range(N):
for c in range(N):
shark_num += shark_maps[r][c]
if shark_num == 1:
print(t)
break
t+=1
# 제일 번호 낮은 얘만 남기고 죽이기
if t > 1000:
print(-1)