ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 2228번 : 구간 나누기
    알고리즘 공부 2020. 5. 5. 16:35

      험멈멈... 왜 어렵지....? 어려울 것 같은 문제가 아니었는데 어렵다! 이럴 수가... 난 바보인가바...


      풀이

      dp를 잘 정의해보자.

     

    dp[n][m] : 첫 번째부터 n번째까지의 수들 중에서 m개의 구간을 선택했을 때 구간 합의 최댓값


      n번째까지의 수 중에서 n번째 숫자가 구간에 포함되지 않았을 경우

      이 경우 n번째 숫자가 없는 것과 마찬가지다.

     

    dp [n][m] = dp [n-1][m]


      n번째까지의 수 중에서 n번째 숫자가 구간에 포함되었을 경우

     

    구간끼리는 인접해서는 안되므로 k-1번째를 비워둬야 한다.

     

      이 경우 n번째 숫자는 마지막 구간, 즉 m번째 구간에 포함되었을 것이다. m번째 구간이 k번째 수부터 n번째 수까지라고 가정해보자. m-1번째 구간은 m번째 구간과 인접할 수 없으므로 k-1번째 수는 사용할 수 없다. 따라서 k-2번째 수까지만 사용해서 m-1개의 구간을 만들어야 한다.

     

    dp [n][m] = dp [k-2][m-1] + sum(k, n)

     

      하지만 m번째 구간이 어디서부터 시작하는지 정확히 알 수 없으므로 for문을 돌려서 최댓값을 구해야 한다.

     

    #include <iostream>
    
    using namespace std;
    
    int n, m;
    bool visit[102][52];
    int dp[102][52];
    int sum[102];
    
    int areaSum(int num, int area)
    {
        if(area == 0) return 0;
        if(num < 2*area-1) return -987654321;
        if(visit[num][area]) return dp[num][area];
        
        visit[num][area] = true;    
        dp[num][area] = areaSum(num-1, area);
            
        for(int i = num; i >= 1; i--)
        {
            dp[num][area] = max(dp[num][area], sum[num] - sum[i-1] + areaSum(i-2, area-1));
        }
        
        return dp[num][area];
    }
    
    int main()
    {
        ios_base :: sync_with_stdio(false);
        cin.tie(NULL);
        cout.tie(NULL);
     
        cin >> n >> m;
    
        int seq;
        for(int i = 1; i <= n; i++)
        {
            cin >> seq;
            sum[i] = sum[i-1] + seq;
        }
        
        cout << areaSum(n, m);
        
        return 0;
    }

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

    백준 2666번 : 벽장문의 이동  (0) 2020.05.07
    백준 2229번 : 조 짜기  (0) 2020.05.07
    백준 1720번 : 타일 코드  (1) 2020.05.04
    백준 1695번 : 팰린드롬 만들기  (0) 2020.05.03
    백준 2662번 : 기업투자  (0) 2020.05.02
Designed by Tistory.