ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 1695번 : 팰린드롬 만들기
    알고리즘 공부 2020. 5. 3. 21:13

      팰린드롬 관련 문제를 예전에 푼 적이 있어서 조금 더 수월하게 풀었던 것 같다. 그때는 팰린드롬인지 아닌지를 판별하는 문제였지만 이번에는 팰린드롬이 되기 위해서 숫자가 얼마나 더 필요한지에 대한 문제였다.


      풀이

      dp 문제는 dp를 잘 정의하면 반은 먹고 들어간다.

     

    dp [a][b] : a부터 b까지의 부분 수열을 팰린드롬으로 만들기 위해 끼워 넣어야 할 숫자의 최소 개수

     

      dp를 잘 정의했다면 그다음은 이 dp를 어떻게 확장 또는 축소시켜나갈지를 고민하면 된다.

     

    a번째 수열의 수와 b번째 수열의 수가 같다dp [a][b] = dp [a+1][b-1]

     

      팰린드롬을 만들려고 하는 것이기 때문에 시작 수와 끝 수가 같다면 범위를 줄여나갈 수 있다. 그러면 다르다면 어떻게 될까?

     

    a번째 수열의 수와 b번째 수열의 수가 다르다dp [a][b] = min(dp [a+1][b], dp [a][b-1]) + 1

     

      다르다면 팰린드롬으로 맞춰주기 위해서 숫자를 끼워 넣어야 한다. 이때 두 가지 경우의 수가 있다. a번째 수열에 대응하도록 제일 뒤쪽에 수를 넣는 방법b번째 수열에 대응하도록 제일 앞쪽에 수를 넣는 방법이 있다. 끼워 넣는 숫자의 개수를 최소화하고 싶으므로 min함수를 이용해서 둘 중 작은 값을 택한다. 그리고 어찌 됐는 팰린드롬으로 만들기 위해서는 숫자 하나를 추가해야 하기 때문에 1을 더해준다.


      초기화 및 계산

      dp를 위와 같이 정의하면 dp [2][2] 같은 값은 0이 되어야 한다. 따라서 dp에서 자주 쓰이는 0이면 계산하고 0이 아니면 계산하지 않는다 같은 테크닉을 쓸 수가 없다. 대신 dp의 기본값을 -1로 초기화시켜준 후 -1이면 계산하고 -1이 아니면 계산하지 않는다를 사용했다.

     

      또한 계산할 때 단순히 이중 for문으로만 하기 어려워서 dfs와 같은 재귀 형식을 채택했다. pelin(a, b)를 계산할 때 a와 b가 같으면 추가해야 할 숫자는 없고, a가 b보다 큰 경우는 있어서는 안 되므로 그때도 0을 리턴했다.

     

    #include <iostream>
    
    using namespace std;
    
    int n;
    int seq[5002];
    int dp[5002][5002];
    
    int pelin(int a, int b)
    {
        if(dp[a][b] != -1) return dp[a][b];
        if(a >= b)
        {
            dp[a][b] = 0;
            return dp[a][b];
        }
        
        if(seq[a] == seq[b]) dp[a][b] = pelin(a+1, b-1);
        else dp[a][b] = min(pelin(a, b-1), pelin(a+1, b)) + 1;
        
        return dp[a][b];
    }
    
    int main()
    {
        cin >> n;
        
        for(int i = 0; i < n; i++)
        {
            cin >> seq[i];
            for(int j = 0; j < n; j++)
            {
                dp[i][j] = -1;
            }
        }
        
        
        for(int i = 0; i < n-1; i++)
        {
            for(int j = i+1; j < n; j++)
            {
                pelin(i, j);
            }
        }
        
        cout << dp[0][n-1];
    
        return 0;
    }

    '알고리즘 공부' 카테고리의 다른 글

    백준 2228번 : 구간 나누기  (1) 2020.05.05
    백준 1720번 : 타일 코드  (1) 2020.05.04
    백준 2662번 : 기업투자  (0) 2020.05.02
    백준 1563번 : 개근상  (0) 2020.05.01
    백준 2482번 : 색상환  (0) 2020.04.30
Designed by Tistory.