백준 풀이
백준 / python / 1584. 게임
땡구리
2023. 2. 1. 13:12
https://www.acmicpc.net/problem/1584
문제 요약
501 x 501 지도가 있다. 지도의 일부분을 밟으면 체력이 1 닳고 지도의 일부분은 접근할 수 없다.
(0, 0) 에서 (500, 500) 까지 이동할 때 받는 최소한의 데미지를 구하라.
풀이 요약
1. bfs 로 푼다.
2. 큐에는 이동 좌표와 함께 이때까지 받은 데미지를 추가한다.
3. 이미 더 적은 데미지를 가지고 방문한 적이 있다면 큐에 넣지 않는다.
주의사항
1. 그냥 deque 로는 시간초과난다. heap 을 쓰거나 zero-one bfs 를 사용해야한다..
2. 움직일 수 있는 방향이 8방향인지 4방향인지 실수하지 말자.
3. bfs 에서 queue 대신 heap 을 쓰면 dijkstra 다.
4. 올바른 좌표값인지 확인할 때 if x in range(501) 등을 사용하면 x < 0 or x > 500 보다 250배 느려진다.
5. 반복되는 코드를 함수로 만들면 실행속도가 빨라진다.
from sys import stdin
from collections import deque
input = stdin.readline
moves = [
(0, -1),
(-1, 0),
(1, 0),
(0, 1),
]
graph = [[0] * 501 for _ in range(501)]
def check_rect(num):
N = int(input())
for _ in range(N):
x1, y1, x2, y2 = map(int, input().split())
left, right = sorted([x1, x2])
top, bottom = sorted([y1, y2])
for x in range(left, right + 1):
for y in range(top, bottom + 1):
graph[y][x] = num
def bfs():
# (damage, x, y)
q = deque([(0, 0, 0)])
while q:
damage, x, y = q.popleft()
if x == 500 and y == 500:
return damage
for dx, dy in moves:
nx = x + dx
ny = y + dy
if 0 <= nx <= 500 and 0 <= ny <= 500:
if graph[ny][nx] == 2:
continue
ndamage = damage + graph[ny][nx]
if not graph[ny][nx]:
q.appendleft((ndamage, nx, ny))
else:
q.append((ndamage, nx, ny))
graph[ny][nx] = 2
return -1
for i in [1, 2]:
check_rect(i)
print(bfs())