티스토리 뷰
728x90
반응형
문제 요약
- 알고리즘 분류:BFS, 시뮬레이션
- 난이도: Gold3
- 문제내용:
- 0은 길 1은 벽이다.
- 벽은 한번 부수고 이동가능하다.
- (0, 0) ~ (N, M)까지의 거리를 구해라
문제풀이
이번에는 문제 유형은 그래프 탐색중에 BFS탐색 알고리즘이다. BFS 탐색 알고리즘에 대한 설명은 여기에서 확인 해보면된다.
import sys
from collections import deque
input = sys.stdin.readline
INF = 1000 * 1000
def bfs():
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
field = [[INF] * M for _ in range(N)]
field[0][0] = 1
queue = deque([(0, 0)])
while queue:
x, y = queue.popleft()
for i in range(4):
fx, fy = x + dx[i], y + dy[i]
if 0 <= fx < N and 0 <= fy < M and matrix[fx][fy] == 0 and field[fx][fy] == INF:
field[fx][fy] = field[x][y] + 1
queue.append((fx, fy))
return field[N-1][M-1]
N, M = map(int, input().split())
matrix = []
for _ in range(N):
array = []
for i in input()[:-1]:
array.append(int(i))
matrix.append(array)
walls = []
for x in range(N):
for y in range(M):
if matrix[x][y] == 1:
walls.append((x, y))
min_value = bfs()
for x, y in walls:
matrix[x][y] = 0
min_value = min(bfs(), min_value)
matrix[x][y] = 1
print(-1 if min_value == INF else min_value)
이번 문제는 가로 세로 1000이고 위 코드 처럼 브루드포스로 모든 벽을 한 번씩 부수고 탐색하면 O(N ^ 4)이상 나와서 시간 초과가 나올것이다.
문제 접근 방법
위 코드 처럼 모든 벽을 탐색하지말고 벽을 부수지 않고 이동하는 경우와 벽을 부수고 이동한 경우를 두 가지 경우를 동시에 탐색 할것이다. 그럼 일단 정상적으로 이동할 경우 2차원 배열과 벽을 부수고 이동하는 2차원 배열을 합쳐서 3차원 배열로 만들것이다.
그러면 2가지 경우만 생각하면된다. 벽을 만날경우 이전에 벽을 한번 부수고 이동하나 벽을 안 부수고 이동하나 벽을 한번도 안 부수고 온 경우에는 벽을 부수고 이동하는 배열로 이동하면 된다. 하지만 벽을 한번 부수고 이동할 경우에는 탐색 취소 시킨다. 그 외 경우는 BFS 알고리즘 처럼 하면된다.
정리
- 기존 미로와 벽을 부수고 이동할 미로 3차원 배열을 만든다.
- 기존 로직에 벽을 만났을때 이전 탐색한노드에서 기존 미로에서 이동한 경우와 벽을 부수고 이동한 미로에서 처리하는 로직을 추가한다.
Code
Python
import sys
from collections import deque
input = sys.stdin.readline
INF = 1000 * 1000 # 최대값
def bfs():
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]
field = [[[INF, INF] for _ in range(M)]for _ in range(N)]
field[0][0][0] = 1
queue = deque([(0, 0, 0)])
while queue:
x, y, flag = queue.popleft() # x, y는 좌표 flag는 이전에 벽을 뚫었는지
for i in range(4):
fx, fy = x + dx[i], y + dy[i]
if 0 <= fx < N and 0 <= fy < M:
# 일반적인 경우
if matrix[fx][fy] == 0 and field[fx][fy][flag] == INF:
field[fx][fy][flag] = field[x][y][flag] + 1
queue.append((fx, fy, flag))
# 벽이 있는데 이전에 벽을 안뚫었을 경우
elif matrix[fx][fy] == 1 and flag == 0:
field[fx][fy][1] = field[x][y][flag] + 1
queue.append((fx, fy, 1))
result = min(field[N-1][M-1])
return -1 if result == INF else result
N, M = map(int, input().split())
matrix = []
for _ in range(N):
array = []
for i in input()[:-1]:
array.append(int(i))
matrix.append(array)
print(bfs())
728x90
반응형
'알고리즘 > 백준' 카테고리의 다른 글
[BAEKJOON]1167 트리의 지름 - Python (0) | 2022.12.28 |
---|---|
[BAEKJOON]2377 Pottery - Visual Basic (0) | 2022.12.28 |
[BAEKJOON]2377 Pottery - FreeBASIC (0) | 2022.12.24 |
[BAEKJOON]2372 Livestock Count - Ada (0) | 2022.12.24 |
[BAEKJOON]1809 Moo - Golfscript (2) | 2022.12.24 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Greedy
- Python
- 동적 계획법
- 그래프
- 동적계획법
- 배열
- JSCODE
- Programmerse
- java
- 조합
- 자바
- BFS
- 문자열
- 재귀호출
- 수학
- LeetCode
- 백준
- DP
- 그리디
- 파이썬
- level2
- 누적합
- 이론
- 알고리즘
- DFS
- 구현
- 백트레킹
- 넓이 우선 탐색
- BaekJoon
- spring-boot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함