BOJ 5561 - 과자의 분할

image.png

dp[i][j]=dp[i][j]= ii 개 까지의 과자 중, ii 번째 과자를 포함해서 길이 jj 를 만들 수 있는 최소 힘

토글링으로 공간복잡도 O(N)O(N) 에 풀 수 있다.

ii개에서 길이 jj를 만든다는 것은 jjiji-j 를 만들 수 있다는 것이다.

dp[i1][j1]dp[i-1][j-1]i1i-1 번째 과자를 포함해서 j1j-1 개의 조각을 만든 것이므로 ii 번째 과자를 그대로 붙여주어서 dp[i][j]=dp[i1][j1]dp[i][j]=dp[i-1][j-1] 로 해주어도 문제없다.

근데 i1i-1 번째 조각을 포함해서 j1j-1 개를 만든 것 말고 i1i-1 번째 조각을 포함하지 않고 j1j-1 개를 만든 것의 최소힘은 dp[i1][ij]dp[i-1][i-j] 이다.

왜냐면 길이 i1i-1 에서 j1j-1 개를 만든다는 것은 iji-j 개를 만들 수도 있다는 것을 의미하기 때문이다.

따라서

dp[i][j]=Max{dp[i1][j1](j1)dp[i1][ij]+a[i1](j1)a[i1](j=1) \begin{aligned} dp[i][j]=Max\begin{cases} dp[i-1][j-1]&(j \ne 1)\\ dp[i-1][i-j]+a[i-1]&(j \ne 1)\\ a[i-1] &(j=1) \end{cases} \end{aligned}

j=1j=1 일 땐, ii 를 포함하여 11 개의 과자를 얻는데 필요한 최소 힘이므로 무조건 a[i1]a[i-1] 이다.

i=1i=1 이면 a[i1]a[i-1] 이 존재하지 않기 때문에 구현상 처리할 필요 없다.

void solve() {  
   int n;  
   cin >> n;  
   vvi dp(2, vi(n + 1));  
   for (int i = 2; i <= n; i++) {  
      int I = i & 1, J = I ^ 1;  
      int x;  
      cin >> x;  
      for (int j = i; j > 1; j--) {  
         dp[I][j] = min(dp[J][j - 1], dp[J][i - j] + x);  
      }  
      dp[I][1] = x;  
   }  
   cout << dp[0][n / 2];  
}

Tags:

Categories:

Updated:

Comments