728x90
시간 제한 1초, 메모리 제한 256MB
# 조건
- 산으로 둘러싸인 고리분지에 사는 아기돼지 삼형제는 엄마돼지로부터 독립하여 새 집을 지으려 합니다.
- 고리분지는 N × M 크기의 2차원 격자로 나타낼 수 있고 각 칸의 지형은 초원, 빙판, 산 중 하나입니다.
- 고리분지에는 돼지가족들 뿐만 아니라 늑대들도 살고 있습니다.
- 늑대는 상하좌우 인접한 칸 중 산이 아닌 칸으로 이동할 수 있습니다.
- 만약 이동한 칸이 빙판이라면 초원을 밟거나 산에 부딪칠 때까지 이동한 방향으로 미끄러집니다.
- 산에 부딪친 경우 늑대는 빙판 위에 가만히 서있을 수 있고 다시 다른 방향으로 이동할 수 있습니다.
- 게으른 아기돼지들은 지푸라기로 집을 지을 예정이기 때문에 늑대가 집이 있는 칸에 도착하기만 한다면 손쉽게 침입할 수 있습니다.
- 고리분지에 사는 늑대들이 도달할 수 없고 지형이 초원인 칸을 '안전한 곳'이라고 부릅니다.
- 게으른 아기돼지들을 위해 고리분지의 지도가 주어지면 지도 위에 모든 안전한 곳의 위치를 표시해주세요.
입력
- 첫 번째 줄에는 격자의 행의 수를 나타내는 N (3 ≤ N ≤ 100) 과 격자의 열의 수를 나타내는 M (3 ≤ M ≤ 100) 이 주어집니다.
- 두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열들이 주어집니다.
- i+1번째 줄의 j번째 문자는 i번째 행 j번째 열의 지형 종류를 의미하며 '
.
' 일 경우 초원, '+
' 일 경우 빙판, '#
' 일 경우 산, 그리고 'W
'는 늑대가 살고 있음을 나타냅니다. - 늑대가 사는 칸은 여러 개일 수 있고 늑대가 사는 지형은 항상 초원입니다.
- 지도의 첫 번째, N번째 행과 첫 번째, M번째 열은 항상 산입니다.
출력
- 입력으로 주어진 지도를 출력하되 아기돼지가 살 수 있는 초원은 문자 'P'로 대체하여 출력합니다.
# 접근 방법
- 입력을 받은 후 늑대 위치와 초원 위치를 리스트와, 딕셔너리에 기록해준다.
- 늑대의 경우 - 번호 : 인덱스, 초원의 경우 (x좌표, y좌표) : 1
- 늑대를 순회하며 위의 조건에 따라 이동시켜준다.
- 초원을 밟는 경우 초원 딕셔너리에서 0으로 변경해준다.
- 빙판을 밟는 순간 이동 가능한 방향으로 이동하며 초원인 경우 초원을 q에 넣어주고, 산을 만나는 경우 마지막 빙판을 q에 넣어준다.
- 늑대가 이동가능한 모든 곳을 확인 한 후 초원 딕셔너리에 남아있는 곳을 P로 변경한 후 출력해주면 된다.
- 주의할 점은, visited 처리를 모두 해주지만, 빙판을 만나서 초원 또는 산을 만나러 갈 때에는 visited를 확인해주지 않아야 한다.
- 아래와 같은 경우 아래에서 위로 올라오는 빙판길이 존재하지만 중간에 빙판길이 먼저 VISITED 처리가 되어 1행의 초원을 밟지 못하는 경우가 발생할 수 있기 때문이다.
# # . # # W + + + # . # + # # . # + # # . . . # #
import sys
sys.stdin = open('input.txt')
input = sys.stdin.readline
from collections import deque
def bfs():
visited = [[0] * M for _ in range(N)]
# 모든 늑대들 q에 넣어주기 + 이동방향 -1로
q = deque()
for i, j in wolf:
q.append((i, j))
visited[i][j] = 1
while q:
si, sj = q.popleft()
for d in range(4):
ni, nj = si+ di[d], sj + dj[d]
if 0<=ni<N and 0<=nj<M:
# 초원이라면 바로 q에 추가
if arr[ni][nj] == '.' and visited[ni][nj] == 0:
q.append((ni, nj))
grassland[(ni, nj)] = 0
visited[ni][nj] = 1
# 빙판이라면 끝까지 가기
elif arr[ni][nj] == '+':
while 0<=ni<N and 0<=nj<M:
# 산이라면 하나빼서 저장
if arr[ni][nj] == '#':
ni -= di[d]
nj -= dj[d]
break
elif arr[ni][nj] == '.':
# 초원인 경우 방문하지 않았다면 표시
if visited[ni][nj] == 0:
grassland[(ni, nj)] = 0
break
ni += di[d]
nj += dj[d]
# 첫방문이면 방문처리
if visited[ni][nj] == 0:
visited[ni][nj] = 1
q.append((ni, nj))
N, M = map(int, input().split())
arr = [list(input().rstrip()) for _ in range(N)]
di, dj = [1, -1, 0, 0], [0, 0, 1, -1]
wolf = []
grassland = dict()
for i in range(N):
for j in range(M):
# 늑대 위치 기록
if arr[i][j] == 'W':
wolf.append((i, j))
elif arr[i][j] == '.':
grassland[(i, j)] = 1
bfs()
for loc, can in grassland.items():
if can:
arr[loc[0]][loc[1]] = 'P'
for i in arr:
print(''.join(i))
728x90
'ALGORITHM > DFS, BFS, 그래프 탐색' 카테고리의 다른 글
[프로그래머스 Lv3] 파이썬 - 미로 탈출 명령어 (1) | 2023.07.29 |
---|---|
[백준 14948번] 파이썬 - 군대 탈출하기 (0) | 2023.07.28 |
[프로그래머스 Lv3] 파이썬 - 부대복귀 (0) | 2023.07.22 |
[백준 3109번] 파이썬 - 빵집 (0) | 2023.07.08 |
[백준 11967번] 파이썬 - 불 켜기 (0) | 2023.07.07 |