p[i]: i번째 파일 크기
$O(n^3)$
dp[i][j]: p[i...j]를 합칠때 드는 최소 비용
dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum(p[i...j])
#include<cstdio> int t, n, s[501], dp[501][501]; int main() { for (scanf("%d", &t); t--;) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", s + i), s[i] += s[i - 1]; for (int i = 2; i <= n; i++) { for (int j = i; --j;) { dp[j][i] = 2e9; for (int k = j; k <= i; k++) if (dp[j][i] > dp[j][k] + dp[k + 1][i]) dp[j][i] = dp[j][k] + dp[k + 1][i]; dp[j][i] += s[i] - s[j - 1]; } } printf("%d\n", dp[1][n]); } return 0; }
$O(n^2)$
a<=b<=c<=d인 a,b,c,d에 대해
1) sum(p[a...c])+sum(p[b...d])<=sum(p[b...c])+sum(p[a...d])
2) sum(p[b...c])<=sum(p[a...d])
이므로 knuth optimization을 적용할 수 있다.
dp[i][j]: p[i+1...j]를 합칠 때 드는 최소 비용
opt[i][j]: dp[i][j]를 구할 때 사용한 최적 k
#include<cstdio> int t, n, dp[501][501], opt[501][501], s[501]; int main() { for (scanf("%d", &t); t--;) { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", s + i); s[i] += s[i - 1]; opt[i - 1][i] = i; } for (int i = 2; i <= n; i++) { for (int j = 0; j + i <= n; j++) { dp[j][j + i] = 2e9; for (int k = opt[j][j + i - 1]; k <= opt[j + 1][j + i]; k++) { if (dp[j][j + i]>dp[j][k] + dp[k][j + i]) { dp[j][j + i] = dp[j][k] + dp[k][j + i]; opt[j][j + i] = k; } } dp[j][j + i] += s[j + i] - s[j]; } } printf("%d\n", dp[0][n]); } return 0; }
댓글 없음 :
댓글 쓰기