문제풀이/백준oj

[백준OJ] 2096번 내려가기

Hyeon-Uk 2021. 6. 5. 23:17
반응형

https://www.acmicpc.net/problem/2096

 

2096번: 내려가기

첫째 줄에 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 숫자가 세 개씩 주어진다. 숫자는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 중의 하나가 된다.

www.acmicpc.net


 

-풀이-

DP를 이용하여 문제를 풀었다.

최대와 최소는 min, max만 따로 구별하면 되므로, max를 예로 들어보겠다.

현재까지 첫번째 칸, 두번째칸 , 세번째 칸까지 최고비용을 ma[0],ma[1],ma[2] 에 담았다고 하자.

다음칸으로 내려갈때, 다음칸의 첫번째칸, 두번째칸, 세번째칸의 최대비용은 어떻게 구할까?

 

이런식으로 존재한다 했을때, a로 갈 수 있는 칸은 1번칸과 2번칸이다. 따라서 다음 1번칸(ma[0]) 을 갱신해주기위해, a`과 b`중 큰 값을 a와 더해서 ma[0]에 넣어주어야한다.

 

b로 갈 수 있는 칸은, 1번 2번 3번 모두다이다. 2번칸(ma[1]) 을갱신해주기 위해서 a`,b`,c`중 제일 큰값을 구해 b와 더해서 ma[1]에 넣어주어야 한다.

 

c로 갈 수 있는 칸은 2번,3번칸이다. 따라서 3번칸(ma[2])을 갱신해주기 위해서는 b`과 c`중 큰값을 구해 c와 더해서 ma[2]에 넣어주어야 한다.

 

이때, 계산하기전에 각 a` , b` , c` 을 뽑아서 임시변수에 저장을 해야한다. 왜냐하면 1번칸을 갱신하면, 2번칸을 계산할때, 갱신된 1번칸의 값이 적용되기때문이다. 

 

마지막 층까지 계산을 마치면, 1번칸 2번칸 3번칸 중 제일 큰 값을 출력해주면 된다.

 

최솟값은 반대로 해주면 된다.

 

-시간복잡도-

각층마다 단순계산이므로, O(N)이된다.

 

-코드-

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int mi[3], ma[3];

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		if (i == 0) {
			mi[0] = ma[0] = a;
			mi[1] = ma[1] = b;
			mi[2] = ma[2] = c;
		}
		else {
			int t1 = mi[0], t2 = mi[1],t3=mi[2];
			mi[0] = min(t1 + a, t2 + a);
			mi[1] = min(t1 + b, min(t2 + b, t3 + b));
			mi[2] = min(t2 + c, t3 + c);

			t1 = ma[0];
			t2 = ma[1];
			t3 = ma[2];
			ma[0] = max(t1 + a, t2 + a);
			ma[1] = max(t1 + b, max(t2 + b, t3 + b));
			ma[2] = max(t2 + c, t3 + c);
		}
	}
	cout << max(ma[0], max(ma[1], ma[2])) << " " << min(mi[0], min(mi[1], mi[2])) << "\n";
	return 0;
}
반응형