문제
https://www.acmicpc.net/problem/2096
걸린 시간
-
풀이
C++
#include <stdio.h>
#include <iostream>
#include <string.h> // memset
using namespace std;
#define INF 987654321
int N;
int arr[100000][3];
int c1[2][3]; // max
int c2[2][3]; // min
// 반복적인 dp 풀이 : Bottom-Up
int iterative1(){
// 기저 사례 : N 층의 값 초기화
for(int x = 0; x < 3; x++)
c1[(N-1)%2][x] = arr[(N-1)][x];
for(int y = N-2; y >= 0; y--){
for(int x = 0; x < 3; x++){
if(x == 0)
c1[y%2][x] = max({c1[(y+1)%2][x], c1[(y+1)%2][x+1]}) + arr[y][x];
else if(x == 1)
c1[y%2][x] = max({c1[(y+1)%2][x-1], c1[(y+1)%2][x], c1[(y+1)%2][x+1]}) + arr[y][x];
else
c1[y%2][x] = max({c1[(y+1)%2][x-1], c1[(y+1)%2][x]}) + arr[y][x];
}
}
return max({c1[0][0], c1[0][1], c1[0][2]});
}
int iterative2(){
// 기저 사례 : N 층의 값 초기화
for(int x = 0; x < 3; x++)
c2[(N-1)%2][x] = arr[(N-1)][x];
for(int y = N-2; y >= 0; y--){
for(int x = 0; x < 3; x++){
if(x == 0)
c2[y%2][x] = min({c2[(y+1)%2][x], c2[(y+1)%2][x+1]}) + arr[y][x];
else if(x == 1)
c2[y%2][x] = min({c2[(y+1)%2][x-1], c2[(y+1)%2][x], c2[(y+1)%2][x+1]}) + arr[y][x];
else
c2[y%2][x] = min({c2[(y+1)%2][x-1], c2[(y+1)%2][x]}) + arr[y][x];
}
}
return min({c2[0][0], c2[0][1], c2[0][2]});
}
int main(){
scanf("%d", &N);
memset(arr, -1, sizeof(arr));
for(int i = 0; i < N; i++)
scanf("%d %d %d", &arr[i][0], &arr[i][1], &arr[i][2]);
printf("%d %d\n", iterative1(), iterative2());
return 0;
}
재귀적 동적 계획법은 30만 크기의 int 형 배열이 3개가 필요하다. 300,000 * 4 * 3 = 3,600,000
byte 로 메모리 제한 4mb 를 통과할 것 같지만 사용환경에 따라서 sizeof(int) 의 크기는 달라질 수 있기 때문에 메모이제이션 대신 다른 방법을 사용해야한다.
재귀적인 구조(Top-Down)를 반복적(Bottom-Up)으로 변경하면 부분 문제가 계산되는 순서들이 일정하게 되어 슬라이딩 윈도우 기법을 사용할 수 있다. 이는 과거에 계산한 값을 모두 저장하는 메모이제이션과 달리 이전의 정보만 저장하기 때문에 메모리가 훨씬 절약된다.
'Baekjoon' 카테고리의 다른 글
Baekjoon 11403번 경로 찾기 (0) | 2020.08.27 |
---|---|
Baekjoon 19590번 비드맨 (0) | 2020.08.25 |
Baekjoon 11003 최솟값 찾기 (0) | 2020.08.21 |
Baekjoon 19572번 가뭄(Small) (0) | 2020.08.18 |
Baekjoon 1389번 케빈 베이컨의 6단계 법칙 (0) | 2020.08.17 |
댓글