2 분 소요

문제

백준 4883번 문제
이 문제는 삼각 그래프의 가장 위쪽 가운데 정점에서 가장 아래쪽 가운데 정점으로 가는 최단 경로를 찾는 문제이다.

삼각 그래프는 사이클이 없는 그래프로 N ≥ 2 개의 행과 3열로 이루어져 있다. 삼각 그래프는 보통 그래프와 다르게 간선이 아닌 정점에 비용이 있다. 어떤 경로의 비용은 그 경로에서 지나간 정점의 비용의 합이다.

4883_p_01.png

오른쪽 그림은 N = 4인 삼각 그래프이고, 가장 위쪽 가운데 정점에서 가장 아래쪽 가운데 정점으로 경로 중 아래로만 가는 경로의 비용은 7+13+3+6 = 29가 된다. 삼각 그래프의 간선은 항상 오른쪽 그림과 같은 형태로 연결되어 있다.

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 그래프의 행의 개수 N이 주어진다. (2 ≤ N ≤ 100,000) 다음 N개 줄에는 그래프의 i번째 행에 있는 정점의 비용이 순서대로 주어진다. 비용은 정수이며, 비용의 제곱은 1,000,000보다 작다.

입력의 마지막 줄에는 0이 하나 주어진다.

출력

각 테스트 케이스에 대해서, 가장 위쪽 가운데 정점에서 가장 아래쪽 가운데 정점으로 가는 최소 비용을 테스트 케이스 번호와 아래와 같은 형식으로 출력한다.

k. n

k는 테스트 케이스 번호, n은 최소 비용이다.

예제 입력 1 복사

4
13 7 5
7 13 6
14 3 12
15 6 16
0

예제 출력 1 복사

1. 22

풀이

각 정점에 올 수 있는 가짓수를 계산해보면 된다
첫째줄은 예외로 두고 둘째줄부터 다음과 같은 공식이 성립

d[i][0] = d[i-1][0], d[i-1][1] 중 최솟값 
d[i][1] = d[i-1][0], d[i-1][1], d[i-1][2], d[i][0] 중 최솟값
d[i][2] = d[i-1][1], d[i-1][2], d[i][1] 중 최솟값

2번째 줄부터 한 노드에 몇개의 화살표가 꽂히는지 그림에서 잘 확인해보자

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
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;

const int mx = 100005;
int arr[mx][3];
int d[mx][3];

int main(void) 
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	int t = 0;
	int n;
	while (true)
	{
		cin >> n;
		if(n == 0)
			break;
		

		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < 3; j++)
				cin >> arr[i][j];
		}

		d[0][0] = 0x3f3f3f3f;
		d[0][1] = arr[0][1];
		d[0][2] = arr[0][1] + arr[0][2];
		for (int i = 1; i < n; i++)
		{
			d[i][0] = arr[i][0] + min(d[i - 1][0], d[i - 1][1]);
			d[i][1] = arr[i][1] + min({ d[i - 1][0], d[i - 1][1], d[i - 1][2], d[i][0] });
			d[i][2] = arr[i][2] + min({ d[i - 1][1], d[i - 1][2], d[i][1] });
		}
		
		cout << ++t << ". ";
		cout << d[n - 1][1] << "\n";
	}
}

댓글남기기