반응형

치즈

티어 : Gold 5
시간 제한 : 1 초
메모리 제한 : 128 MB
알고리즘 분류 : 구현, 그래프 이론, 그래프 탐색, 너비 우선 탐색, 시뮬레이션

 

문제

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓여 있지 않으며 치즈에는 하나 이상의 구멍이 있을 수 있다.

이 치즈를 공기 중에 놓으면 녹게 되는데 공기와 접촉된 칸은 한 시간이 지나면 녹아 없어진다. 치즈의 구멍 속에는 공기가 없지만 구멍을 둘러싼 치즈가 녹아서 구멍이 열리면 구멍 속으로 공기가 들어가게 된다. <그림 1>의 경우, 치즈의 구멍을 둘러싼 치즈는 녹지 않고 ‘c’로 표시된 부분만 한 시간 후에 녹아 없어져서 <그림 2>와 같이 된다.

 

<그림 1> 원래 치즈 모양

다시 한 시간 후에는 <그림 2>에서 ‘c’로 표시된 부분이 녹아 없어져서 <그림 3>과 같이 된다.

<그림 2> 한 시간 후의 치즈 모양
<그림 3> 두 시간 후의 치즈 모양

<그림 3>은 원래 치즈의 두 시간 후 모양을 나타내고 있으며, 남은 조각들은 한 시간이 더 지나면 모두 녹아 없어진다. 그러므로 처음 치즈가 모두 녹아 없어지는 데는 세 시간이 걸린다. <그림 3>과 같이 치즈가 녹는 과정에서 여러 조각으로 나누어 질 수도 있다.

입력으로 사각형 모양의 판의 크기와 한 조각의 치즈가 판 위에 주어졌을 때, 공기 중에서 치즈가 모두 녹아 없어지는 데 걸리는 시간과 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 치즈가 없는 칸은 0, 치즈가 있는 칸은 1로 주어지며 각 숫자 사이에는 빈칸이 하나씩 있다.

 

출력

첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력한다.

 

예제 입출력


Algorithm

DFS - 재귀, 구현
1. 1시간마다 DFS를 이용해 치즈에 구멍이 있는지 확인
    ☞ 0으로된 덩어리가 2개 이상인 경우 구멍 존재
2. 구멍이 존재하면 구멍에 해당하는 칸의 값을 H로 변경
3. graph를 한 번씩 돌면서 현재 위치가 1인데 상, 하, 좌, 우 중 한 칸이라도 0이 존재하면 이번에 삭제되는 칸
    ☞ 해당 칸의 값을 C로 변경
4. 매 번 C의 개수와 1의 개수의 차를 확인해 0인 경우 반복문 break

 

Code

def dfs(x, y, replace_value):
    
    # graph 밖으로 벗어나면 False Return
    if x < 0 or x > N-1 or y < 0 or y > M-1:
        return False
    
    # 이미 방문했던 칸이거나 0이 아니면 False Return
    if visited[x][y] or graph[x][y] != 0:
        return False
    
    # 현재 위치 방문 기록
    visited[x][y] = True
    # 구멍인 경우 H로 변경
    graph[x][y] = replace_value
    
    # 상하좌우로 이동
    dfs(x-1, y, replace_value)
    dfs(x+1, y, replace_value)
    dfs(x, y-1, replace_value)
    dfs(x, y+1, replace_value)

import sys
input = sys.stdin.readline

N, M = map(int, input().split())
sys.setrecursionlimit(N*M)
graph = []
count_cheezes = 0 # 치즈가 녹기 전 치즈조각이 놓여 있는 칸의 개수
for _ in range(N):
    graph.append(list(map(int, input().split())))
    count_cheezes += graph[-1].count(1)

num = 0
while True:

    # 구멍의 값을 H로 변경
    visited = [[False for _ in range(M)] for _ in range(N)]
    for x in range(N):
        for y in range(M):
            # x, y가 0, 0이 아니면 replace 값 H로 설정
            if x > 0 and y > 0:
                dfs(x, y, 'H')
            else:
                dfs(x, y, 0)

    # 가장자리에 있는 1을 C로 변경
    count_c = 0
    for x in range(N):
        for y in range(M):
            if graph[x][y] == 1:
                # 현재 index의 상하좌우 중 한 군데라도 0이 있으면 가장자리
                for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                    nx = x+dx
                    ny = y+dy
                    # graph 밖으로 벗어나면 continue
                    if nx < 0 or nx > N-1 or ny < 0 or ny > M-1:
                        continue
                    
                    # nx, ny가 0이면 x, y를 C로 변경하고 break
                    if graph[nx][ny] == 0:
                        graph[x][y] = 'C'
                        count_c += 1
                        break
    
    # 현재 1인 칸과 없어질 칸의 차가 0이면 break
    if count_cheezes - count_c == 0:
        print(num+1)
        print(count_cheezes)
        break
    
    # C, H인 칸 모두 0으로 변경
    for x in range(N):
        for y in range(M):
            if graph[x][y] == 'C'or graph[x][y] == 'H':
                graph[x][y] = 0
    num += 1
    count_cheezes -= count_c

메모리: 33988 KB
시간: 148 ms

반응형
반응형

음식물 피하기

티어 : Silver 1
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 그래프 이론, 그래프 탐색, 너비 우선 탐색, 깊이 우선 탐색

 

문제

코레스코 콘도미니엄 8층은 학생들이 3끼의 식사를 해결하는 공간이다. 그러나 몇몇 비양심적인 학생들의 만행으로 음식물이 통로 중간 중간에 떨어져 있다. 이러한 음식물들은 근처에 있는 것끼리 뭉치게 돼서 큰 음식물 쓰레기가 된다.

이 문제를 출제한 선생님은 개인적으로 이러한 음식물을 실내화에 묻히는 것을 정말 진정으로 싫어한다. 참고로 우리가 구해야 할 답은 이 문제를 낸 조교를 맞추는 것이 아니다. 

통로에 떨어진 음식물을 피해가기란 쉬운 일이 아니다. 따라서 선생님은 떨어진 음식물 중에 제일 큰 음식물만은 피해 가려고 한다. 

선생님을 도와 제일 큰 음식물의 크기를 구해서 “10ra"를 외치지 않게 도와주자.

 

입력

첫째 줄에 통로의 세로 길이 N(1 ≤ N ≤ 100)과 가로 길이 M(1 ≤ M ≤ 100) 그리고 음식물 쓰레기의 개수 K(1 ≤ K ≤ N×M)이 주어진다.  그리고 다음 K개의 줄에 음식물이 떨어진 좌표 (r, c)가 주어진다.

좌표 (r, c)의 r은 위에서부터, c는 왼쪽에서부터가 기준이다. 입력으로 주어지는 좌표는 중복되지 않는다.

 

출력

첫째 줄에 음식물 중 가장 큰 음식물의 크기를 출력하라.

 

예제 입출력


Algorithm

DFS - 재귀
1. 쓰레기가 떨어져있는 곳은 1, 쓰레기가 없는 곳은 0으로 두고 graph 구현
2. (0, 0) 부터 (N-1, M-1) 까지 DFS를 이용해 덩어리 당 음식물 개수 확인
3. DFS에서 True 반환될 때마다 음식물 개수 최댓값으로 갱신

 

Code

def dfs(x, y):
    global count_
    
    # graph의 범위를 벗어나면 False Return
    if x < 0 or x > N-1 or y < 0 or y > M-1:
        return False
    
    # 현재 위치에 방문한 적이 있거나 음식물이 없는 곳이면 False Return
    if graph[x][y] == 0:
        return False
    
    # 현재 위치 방문 기록
    graph[x][y] = 0
    count_ += 1
    
    # 인접 노드 방문
    dfs(x-1, y)
    dfs(x+1, y)
    dfs(x, y-1)
    dfs(x, y+1)
    
    return True
    
import sys
input = sys.stdin.readline

# 입력
N, M, K = map(int, input().split())
sys.setrecursionlimit(N*M*K)
graph = [[0 for _ in range(M)] for _ in range(N)]
for _ in range(K):
    x, y = map(int, input().split())
    graph[x-1][y-1] = 1

global count_ # 덩어리에 속해있는 노드 개수
answer = 0
for x in range(N):
    for y in range(M):
        count_ = 0
        # DFS 반환값이 True일 때만 정답 갱신
        if dfs(x, y):
            answer = max(answer, count_)
print(answer)

메모리: 35760 KB
시간: 80 ms

반응형
반응형

촌수계산

티어 : Silver 2
시간 제한 : 1 초
메모리 제한 : 128 MB
알고리즘 분류 : 그래프 이론, 그래프 탐색, 너비 우선 탐색, 깊이 우선 탐색

 

문제

우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.

여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.

 

입력

사람들은 1, 2, 3, …, n (1 ≤ n ≤ 100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다.

각 사람의 부모는 최대 한 명만 주어진다.

 

출력

입력에서 요구한 두 사람의 촌수를 나타내는 정수를 출력한다. 어떤 경우에는 두 사람의 친척 관계가 전혀 없어 촌수를 계산할 수 없을 때가 있다. 이때에는 -1을 출력해야 한다.

 

예제 입출력


Code

from collections import deque

n = int(input())
start, end = map(int, input().split())
m = int(input())
graph = []
visited = []
for i in range(n+1):
    graph.append([])
    visited.append(0)
for _ in range(m):
    x, y = map(int, input().split())
    graph[x].append(y)
    if x not in graph[y]:
        graph[y].append(x)
        
def bfs(start, end):
    queue = deque([start])
    
    while queue:
        now = queue.popleft()
        
        for i in graph[now]: # 인접한 노드를 모두 돌면서
            if visited[i] == 0: # 한 번도 접근한 적 없다면
                queue.append(i) # 큐에 모두 추가
                visited[i] = visited[now] + 1 # 방문 기록
        
        if visited[end] > 0: # 마지막 노드 값이 갱신되면 return
            return visited[end]
        
    if visited[end] == 0: # while문을 다 돌았는데도 마지막 노드 값이 갱신되지 않았다면
        return -1 # -1 return
    
print(bfs(start, end))

메모리: 32404 KB
시간: 96 ms

반응형

'백준 > Python' 카테고리의 다른 글

[백준 6603] 로또 Python  (0) 2022.04.11
[백준 10971] 외판원 순회 2 Python  (0) 2022.04.11
[백준 10819] 차이를 최대로 Python  (0) 2022.04.08
[백준 2606] 바이러스 Python  (0) 2022.04.08
[백준 10974] 모든 순열 Python  (0) 2022.04.08
반응형

바이러스

티어 : Silver 3
시간 제한 : 1 초
메모리 제한 : 128 MB
알고리즘 분류 : 그래프 이론, 그래프 탐색, 너비 우선 탐색, 깊이 우선 탐색

 

문제

신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.

예를 들어 7대의 컴퓨터가 <그림 1>과 같이 네트워크 상에서 연결되어 있다고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2, 3, 5, 6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.

어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서 서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다.

 

출력

1번 컴퓨터가 웜 바이러스에 걸렸을 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 첫째 줄에 출력한다.

 

예제 입출력


Code

# BFS
N = int(input()) # 컴퓨터 수
M = int(input()) # 네트워크 상에서 직접 연결되어있는 컴퓨터 쌍의 수

graph = []
visited = [False] * (N+1)
for i in range(N+1):
    graph.append([])
    
for _ in range(M):
    i, j = map(int, input().split())
    graph[i].append(j)
    if i not in graph[j]:
        graph[j].append(i)
    
# BFS
from collections import deque

def bfs(start):
    queue = deque([start])
      
    while queue:
        now = queue.popleft()
        # 현재 컴퓨터 방문 처리
        visited[now] = True
            
        # 해당 노드의 인접 노드 중 방문하지 않은 노드를 모두 Queue에 삽입하고 방문처리
        for i in graph[now]:
            if not visited[i]:
                queue.append(i)

bfs(1)

count = -1
for i in visited: # 방문한 노드 수 세기
    if i:
        count += 1
print(count)

메모리: 30864 KB
시간: 80 ms

 

Code

# DFS
N = int(input()) # 컴퓨터 수
M = int(input()) # 네트워크 상에서 직접 연결되어있는 컴퓨터 쌍의 수

graph = []
visited = [False] * (N+1)
for i in range(N+1):
    graph.append([])
    
for _ in range(M):
    i, j = map(int, input().split())
    graph[i].append(j)
    if i not in graph[j]:
        graph[j].append(i)
    
# DFS
def dfs(n):
    # 현재 컴퓨터 방문 처리
    visited[n] = True
    # 연결되어있는 컴퓨터 하나씩 방문
    for i in graph[n]:
        if not visited[i]:
            dfs(i)

dfs(1)

count = -1
for i in visited: # 방문한 노드 수 세기
    if i:
        count += 1
print(count)

메모리: 30864 KB
시간: 100 ms

반응형
반응형

연결 요소의 개수

티어 : Silver 2
시간 제한 : 3 초
메모리 제한 : 512 MB
알고리즘 분류 : 그래프 이론, 그래프 탐색, 너비 우선 탐색, 깊이 우선 탐색

 

문제

방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.

 

출력

첫째 줄에 연결 요소의 개수를 출력한다.

 

예제 입출력


Algorithm

DFS 이용
1. 그래프 구성
    ➝ 양방향으로 구성
2. DFS 구현해 덩어리가 하나씩 나올 때마다 COUNT += 1

 

Code

import sys
input = sys.stdin.readline


def dfs(start):

    # 현재 Node가 이미 방문한 Node라면 False Return
    if visited[start]:
        return False
    
    # 현재 Node 방문 처리
    visited[start] = True

    # 이웃노드 중
    for x in graph[start]:
        # 방문하지 않은 노드만 접근
        if visited[x] == False:
            dfs(x)
            
    return True
    
    
# 입력
N, M = map(int, input().split())
sys.setrecursionlimit(10**9)
graph = [[] for _ in range(N+1)]
visited = [False] * (N+1)

for _ in range(M):
    i, j = map(int, input().split())
    graph[i].append(j)
    graph[j].append(i)

# 노드 하나씩 보면서 덩어리 count
count = 0
for x in range(1, N+1):
    if not visited[x] and dfs(x):
        count += 1
        
print(count)

메모리: 64880 KB
시간: 768 ms

반응형

'백준 > Python' 카테고리의 다른 글

[백준 2164] 카드2 Python  (0) 2022.03.23
[백준 18258] 큐 2 Python  (0) 2022.03.23
[백준 1874] 스택 수열 Python  (0) 2022.03.23
[백준 4949] 균형잡힌 세상 Python  (0) 2022.03.21
[백준 1916] 최소비용 구하기 Python  (0) 2022.03.20
반응형

최소비용 구하기

티어 : Gold 5
시간 제한 : 0.5 초
메모리 제한 : 128 MB
알고리즘 분류 : 그래프 이론, 다익스트라

 

문제

N개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 M개의 버스가 있다. 우리는 A번째 도시에서 B번째 도시까지 가는데 드는 버스 비용을 최소화 시키려고 한다. A번째 도시에서 B번째 도시까지 가는데 드는 최소비용을 출력하여라. 도시의 번호는 1부터 N까지이다.

 

입력

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 그리고 그 다음에는 도착지의 도시 번호가 주어지고 또 그 버스 비용이 주어진다. 버스 비용은 0보다 크거나 같고, 100,000보다 작은 정수이다.

그리고 M+3째 줄에는 우리가 구하고자 하는 구간 출발점의 도시번호와 도착점의 도시번호가 주어진다. 출발점에서 도착점을 갈 수 있는 경우만 입력으로 주어진다.

 

출력

첫째 줄에 출발 도시에서 도착 도시까지 가는데 드는 최소 비용을 출력한다.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 입력으로 graph 구성
2. 다익스트라 알고리즘을 이용해 최단 경로 구하기

 

Code

import sys
import heapq

def dijkstra(start):
    queue = []
    
    # 첫 번째 위치 큐에 추가
    heapq.heappush(queue, (0, start))
    distance[start] = 0
    
    while queue:
        # queue에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 이미 방문한 적 있는 도시이면 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            # cost 계산 : 현재 node의 누적 거리 + 현재 노드에서 다음 노드까지의 거리
            cost = dist + next[0]
            # cost가 distance에 저장된 값보다 작으면 갱신
            if cost < distance[next[1]]:
                distance[next[1]] = cost
                heapq.heappush(queue, (cost, next[1]))
                
input = sys.stdin.readline
INF = 1e9

# 입력
N = int(input())
M = int(input())
graph = [[] for _ in range(N+1)]
distance = [INF] * (N+1)
for _ in range(M):
    start, end, cost = map(int, input().split())
    graph[start].append((cost, end))
start, end = map(int, input().split())

dijkstra(start)
print(distance[end])

메모리: 56088 KB
시간: 352 ms

반응형
반응형

최단경로

티어 : Gold 5
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 그래프 이론, 다익스트라

 

문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

 

입력

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

 

출력

첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 입력으로 graph 구성
2. 다익스트라 알고리즘을 이용해 최단 경로 구하기

 

Code

import sys
import heapq

def dijkstra(start):
    queue = []
    # 첫 번째 노드 큐에 추가
    heapq.heappush(queue, (0, start))
    distance[start] = 0
    
    while queue:
        # 큐에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 이미 방문한 노드는 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            # cost 계산 = 현재 node의 거리 + 다음 node까지의 거리
            cost = dist + next[1]
            if cost < distance[next[0]]:
                distance[next[0]] = cost
                # 큐에 추가
                heapq.heappush(queue, (cost, next[0]))

INF = int(1e9)
input = sys.stdin.readline

V, E = map(int, input().split())
start = int(input())
graph = [[] for _ in range(V+1)]
distance = [INF] * (V+1)
for _ in range(E):
    u, v, w = map(int, input().split())
    graph[u].append((v, w))

dijkstra(start)
for i in range(1, V+1):
    if distance[i] == INF:
        print('INF')
    else:
        print(distance[i])

메모리: 66936 KB
시간: 700 ms

반응형
반응형

지름길

티어 : Silver 1
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 다이나믹 프로그래밍, 그래프 이론, 다익스트라

 

문제

매일 아침, 세준이는 학교에 가기 위해서 차를 타고 D킬로미터 길이의 고속도로를 지난다. 이 고속도로는 심각하게 커브가 많아서 정말 운전하기도 힘들다. 어느 날, 세준이는 이 고속도로에 지름길이 존재한다는 것을 알게 되었다. 모든 지름길은 일방통행이고, 고속도로를 역주행할 수는 없다.

세준이가 운전해야 하는 거리의 최솟값을 출력하시오.

 

입력

첫째 줄에 지름길의 개수 N과 고속도로의 길이 D가 주어진다. N은 12 이하인 양의 정수이고, D는 10,000보다 작거나 같은 자연수이다. 다음 N개의 줄에 지름길의 시작 위치, 도착 위치, 지름길의 길이가 주어진다. 모든 위치와 길이는 10,000보다 작거나 같은 음이 아닌 정수이다. 지름길의 시작 위치는 도착 위치보다 작다.

 

출력

세준이가 운전해야하는 거리의 최솟값을 출력하시오.

 

예제 입출력


Algorithm

dijkstra 알고리즘 - 힙
1. 지름길을 입력 받아 graph 생성
    ➝ 도착 지점이 고속도로의 길이보다 큰 경우 graph에 추가하지 않음
2. 지름길이 아닌 길도 graph에 추가
    ➝ 중간에 끊겨있는 길도 같이 추가
3. D 위치의 최단 거리 출력

 

Code

import sys
import heapq

INF = int(1e9)
input = sys.stdin.readline

def dijkstra(start):
    queue = []
    
    # 첫 번째 칸으로 가는 최단 경로 0으로 설정
    heapq.heappush(queue, (start, 0))
    distance[start] = 0
    
    while queue:
        
        # 큐에서 꺼내기
        dist, now = heapq.heappop(queue)
        
        # 방문한 노드라면 무시
        if distance[now] < dist:
            continue
        
        # 인접 노드 확인
        for next in graph[now]:
            cost = dist + next[1]
            
            # cost가 인접노드까지 가는 데 최소 거리라면 갱신하고 큐에 추가
            if cost < distance[next[0]]:
                distance[next[0]] = cost
                heapq.heappush(queue, (cost, next[0]))
    

N, D = map(int, input().split())
graph = [[] for _ in range(D+1)]
distance = [INF] * (D+1)
for _ in range(N):
    start, end, length = map(int, input().split())
    # 도착 지점이 고속도로의 길이보다 큰 경우 graph에 추가하지 않음
    if end > D:
        continue
    graph[start].append((end, length))

    # 지름길이 아닌 길도 graph에 추가
    if (end, end - start) not in graph[start]:
        graph[start].append((end, end - start))
        
for i in range(D):
    # graph의 현재 INDEX에 다음 칸 까지의 거리 추가
    graph[i].append((i+1, 1))

dijkstra(0)
print(distance[-1])

메모리: 32928 KB
시간: 72 ms

반응형

+ Recent posts