https://www.acmicpc.net/problem/2842
알고리즘 분류
- 그래프 이론
- 그래프 탐색
- 이분 탐색
- 너비 우선 탐색
- 두 포인터
문제
상덕이는 언덕 위에 있는 마을의 우체국에 직업을 얻었다. 마을은 N×N 행렬로 나타낼 수 있다. 행렬로 나뉘어진 각 지역은 우체국은 'P', 집은 'K', 목초지는 '.' 중 하나로 나타낼 수 있다. 또, 각 지역의 고도도 알고 있다.
매일 아침 상덕이는 마을의 모든 집에 우편을 배달해야 한다. 배달은 마을에 하나밖에 없는 우체국 'P'가 있는 곳에서 시작한다. 상덕이는 현재 있는 칸과 수평, 수직, 대각선으로 인접한 칸으로 이동할 수 있다. 마지막 편지를 배달하고 난 이후에는 다시 우체국으로 돌아와야 한다.
상덕이는 이렇게 매일 아침 배달을 하는 것이 얼마나 힘든지 궁금해졌다. 상덕이가 배달하면서 방문한 칸 중 가장 높은 곳과 낮은 곳의 고도 차이를 피로도라고 하자. 이때, 가장 작은 피로도로 모든 집에 배달을 하려면 어떻게 해야 하는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. (2 ≤ N ≤ 50)
다음 N개 줄에는 마을을 나타내는 행렬이 주어진다. 'P'는 한 번만 주어지며, 'K'는 적어도 한 번 주어진다.
다음 N개 줄에는 행렬로 나뉘어진 지역의 고도가 행렬 형태로 주어진다. 고도는 1,000,000보다 작거나 같은 자연수이다.
출력
첫째 줄에 가장 작은 피로도를 출력한다.
예제 입출력
풀이
피로도. 즉 고도 차이를 최소화해야한다. 그러므로 투포인터를 통해 최소-최대에 대한 범위를 좁혀나가며 진행하면 된다.
코드
import sys
from collections import deque
input = sys.stdin.readline
D = [(-1, -1), (-1, 0), (-1, 1),(0, -1),(0, 1),( 1, -1), (1, 0), (1, 1)]
ans = 10**9
l,r = 0,0
def calc(lo, h):
if not (lo <= height[px][py] <= h):
return False
visited = [[False]*n for _ in range(n)]
q = deque([(px, py)])
visited[px][py] = True
cnt = 0
while q:
x, y = q.popleft()
if G[x][y] == 'K':
cnt += 1
if cnt == kCnt:
return True
for dx, dy in D:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny]:
if lo <= height[nx][ny] <= h:
visited[nx][ny] = True
q.append((nx, ny))
return False
n = int(input())
G = [list(input().rstrip()) for _ in range(n)]
px, py = 0, 0
H = []
for i in range(n):
for j in range(n):
if G[i][j] == 'P':
px, py = i, j
elif G[i][j] == 'K':
H.append((i, j))
height = [list(map(int, input().split())) for _ in range(n)]
height_ = sorted({h for row in height for h in row})
m = len(height_)
kCnt = len(H)
while l < m and r < m:
if calc(height_[l], height_[r]):
ans = min(ans, height_[r] - height_[l])
l += 1
else:
r += 1
if r == m:
break
print(ans)
'Koala - 17기 > 코딩테스트 심화 스터디' 카테고리의 다른 글
[백준/Python] #30648 트릭플라워 (0) | 2025.01.26 |
---|---|
[백준/Python] 2003번: 수들의 합 2 (0) | 2025.01.26 |
[백준/Python] 14465번 : 소가 길을 건너간 이유 5 (0) | 2025.01.26 |
[백준/C++] 2531번: 회전 초밥 (0) | 2025.01.24 |
[백준/Python] 1700번: 멀티탭 스케줄링 (0) | 2025.01.19 |