Knuth's Optimization in dynamic programming specifically applies for optimal tree problems. It is only applicable for the following recurrence:
This optimization reduces the time complexity from to
Let us examine , the number of iterations that occur when we loop from to instead of from to .
Let represent the length of the current segment.
the amortized time complexity is .
A certain string-processing language allows the programmer to break a string into two pieces. Since this involves copying the old string, it costs units of time to break a string of characters into two pieces. Suppose a programmer wants to break a string into many pieces. The order in which the breaks are made can affect the total amount of time used. For example, suppose we wish to break a character string after characters , , and . If the breaks are made in left-to-right order, then the first break cost units of time, the second break costs units of time, and the third breaks costs units of time, a total of units of time. If the breaks are made in right-to-left order, then the first break costs units of time, the second break costs units of time, and the third break costs units of time, a total of units of time.
Given the length of the string , and places to break the string at, what is the minimum amount of time to break the string?
#include <bits/stdc++.h>
using namespace std;
#define SIZE 1005
long long dp[SIZE][SIZE];
int mid[SIZE][SIZE];
int pos[SIZE];
int n, m;
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 1; i <= m; i++) {
scanf("%d", &pos[i]);
}
pos[0] = 0;
pos[m + 1] = n;
// length of section of cuts to compute
for (int i = 0; i <= m + 1; i++) {
// section of cuts to compute: [j, j + i]
for (int j = 0; j + i <= m + 1; j++) {
if (i < 2) {
dp[j][j + i] = 0ll;
mid[j][j + i] = j;
continue;
}
dp[j][j + i] = 1ll << 60;
// optimal place to cut
for (int k = mid[j][i + j - 1]; k <= mid[j + 1][i + j]; k++) {
long long next = dp[j][k] + dp[k][j + i] + pos[j + i] - pos[j];
if (next < dp[j][j + i]) {
dp[j][j + i] = next;
mid[j][j + i] = k;
}
}
}
}
printf("%lld\n", dp[0][m + 1]);
}
return 0;
}
This post is a part of a series of three posts on dynamic programming optimizations: