• [백준OJ] 2096번 내려가기

    2021. 6. 5.

    by. Hyeon-Uk

    반응형

    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;
    }
    
    반응형

    댓글