ALGOSPOT TRIANGLEPATH

2020.02.17

TRIANGLEPATH

풀이

  • 행을 한칸씩 이동할 때, 아래와 오른쪽 대각선 아래 두가지 경우의 수가 있다.
  • 재귀함수를 이용해서 마지막 행에 도착하는 순간 그때의 최대 거리를 리턴하는 getResult 함수를 만들었다.
  • 처음에 메모이제이션을 마지막에 도달했을 때 최댓 거리를 DP 행렬에 기록하려고 시도했었다.
  • 우연히 정답이 나왔으나 이는 같은 결과가 나올 수 없었다. 경로가 달라질 때마다 마지막에 도달하는 거리는 달라진다.
  • 같은 지점에 대해 같은 결과가 나오는 것에 대해 메모이제이션을 활용해야 하는데 잘못된 알고리즘을 구상한 것이다.

잘못된 메모이제이션 활용

//! 2020.02.17
// TODO AS_TRIANGLEPATH.cpp
// Dynamic Programming
#include<cstdio>
using namespace std;

const int MAX = 105;
int DP[MAX][MAX];
int inMap[MAX][MAX];
int C, N;

void resetMap(int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            DP[i][j] = -1;
            inMap[i][j] = 0;
        }
    }
}

int getResult(int y,int x,int dist) {
    int& ret = DP[y][x];
    if (ret != -1) return ret;
    if (y>=N-1) {
        return ret = dist+inMap[y][x];
    }
    else {
        dist += inMap[y][x];
        int tmpMax1 = -1;
        int tmpMax2 = -1;
        if (x <= y) tmpMax1 = getResult(y+1, x + 1, dist);
        tmpMax2 = getResult(y+1, x, dist);
        return ret = tmpMax1 > tmpMax2 ? tmpMax1 : tmpMax2;
    }
}

int main() {
    scanf("%d", &C);
    resetMap(MAX, MAX);
    for (int c = 0; c < C; c++) {
        scanf("%d", &N);
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < i+1; j++) {
                scanf("%d", &inMap[i][j]);
            }
        }
        printf("%d\n", getResult(0,0,0));
        resetMap(N, N);
    }

    return 0;
}

수정

해당 지점 이후로 가장 큰 경로의 거리를 기록하도록 메모이제이션 활용을 바꿨다.

이렇게 하게 되면 내 다음 경로의 두가지 경우 중 큰 경우를 구해서 기록하게 되는데, 이는 매번 같은 결과일 수 밖에 없었고 문제를 해결할 수 있었다.

올바른 메모이제이션 활용

//! 2020.02.17
// TODO AS_TRIANGLEPATH.cpp
// Dynamic Programming
#include<cstdio>
using namespace std;

const int MAX = 105;
int DP[MAX][MAX];
int inMap[MAX][MAX];
int C, N;

void resetMap(int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            DP[i][j] = -1;
            inMap[i][j] = 0;
        }
    }
}

int getResult(int y,int x) {
    int& ret = DP[y][x];
    if (ret != -1) return ret;
    if (y>=N-1) {
        return ret = inMap[y][x];
    }
    else {
        int tmpMax1 = inMap[y][x];
        int tmpMax2 = inMap[y][x];
        if (x <= y) tmpMax1 += getResult(y+1, x + 1);
        tmpMax2 += getResult(y+1, x);
        return ret = tmpMax1 > tmpMax2 ? tmpMax1 : tmpMax2;
    }
}

int main() {
    scanf("%d", &C);
    resetMap(MAX, MAX);
    for (int c = 0; c < C; c++) {
        scanf("%d", &N);
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < i+1; j++) {
                scanf("%d", &inMap[i][j]);
            }
        }
        printf("%d\n", getResult(0,0));
        resetMap(N, N);
    }

    return 0;
}

'SW > 알고리즘 문제풀이' 카테고리의 다른 글

ALGOSPOT LIS (Longest Increasing Sequence)  (0) 2020.02.18
백준17135 캐슬디펜스  (0) 2020.02.18
ALGOSPOT WILDCARD  (0) 2020.02.17
백준1918 후위 표기식  (0) 2020.02.17
백준17070 파이프 옮기기 1  (0) 2020.02.17