Given a sequence with a length of n, the sequence can be divided into m segments at most, each of which has a right value. The weight is the sum of the two numbers in the sequence multiplied by two. M <= n <= 1000.
Solution: Classic DP optimization questions, which can be optimized using quadrilateral inequality or slope optimization. We can achieve this in three ways: Two slope optimization methods and one quadrilateral inequality, the complexity is n * m, but Changshu is slightly different.
The state transition equation is very good. dp [I] [j] = min (dp [I] [j], dp [k] [J-1] + cost [k + 1] [j]) (1 <= k <I), this equation is written in n * m, when n is 1000, the calculation amount is 1 billion. optimization is required.
First, quadrilateral inequality optimization. This method is the simplest, mainly to reduce the number of enumeration k times. Cost [I] [j] is the weight of a certain range. When the range increases, the weight value increases, the range decreases, and the weight value decreases, in this case, we can use quadrilateral inequality optimization.
We set s [I] [j] to the leading status of dp [I] [j, dp [I] [j] = dp [s [I] [j] [J-1] + cost [s [I] [j] + 1] [j]. then we enumerate k, as long as we enumerate s [I] [J-1] <= k <= s [I + 1] [j], j must traverse from small to large, I must be from large to small.
In this way, my code ran 140 ms.
The second type is slope optimization. It is actually a reference to the idea of Daniel. Here, I just want to introduce myself. The dp and suma arrays in this method must be 64-bit integers, because the sum of squares will exceed 32-bit integers.
In this way, my code ran 350 ms.
The third type is slope optimization. It is actually a reference to the idea of Daniel. Here, I just want to introduce myself. In fact, this question can be used as a template question, so the slope optimization is similar.
In this way, my code ran 109 ms.
Test data:
Input:
4 1
4 5 1 2
4 2
4 5 1 2
5 3
1 2 1 2 1
6 4
7 5 3 6 8 9
10 3
1 4 2 7 5 6 8 5 6 9
OutPut:
17
2
92
15
187
C producer code:
[Cpp]
// Quadrilateral Inequality
# Include <stdio. h>
# Include <string. h>
# Deprecision MAX 1100
# Define INF (1 <30)
Int n, m, sum [MAX], cost [MAX] [MAX];
Int arr [MAX], dp [MAX] [MAX], s [MAX] [MAX];
Void Initial (){
Int I, j, k;
For (I = 1; I <= n; ++ I)
For (j = 1; j <= n; ++ j)
If (j <I) cost [I] [j] = 0;
Else cost [I] [j] = cost [I] [j-1] + arr [j] * (sum [j-1]-sum [I-1]);
For (I = 0; I <= n; ++ I ){
Dp [I] [0] = cost [1] [I];
S [I] [0] = 0, s [n + 1] [I] = n;
}
}
Int Solve_DP (){
Int I, j, k;
For (j = 1; j <= m; ++ j)
For (I = n; I> = 1; -- I ){
Dp [I] [j] = INF;
For (k = s [I] [J-1]; k <= s [I + 1] [j]; + + k)
If (dp [k] [J-1] + cost [k + 1] [I] <dp [I] [j]) {
S [I] [j] = k;
Dp [I] [j] = dp [k] [J-1] + cost [k + 1] [I];
}
}
Return dp [n] [m];
}
Int main ()
{
Int I, j, k;
While (scanf ("% d", & n, & m), n + m ){
For (I = 1; I <= n; ++ I)
Scanf ("% d", & arr [I]), sum [I] = arr [I] + sum [I-1];
Initial ();
Int ans = Solve_DP ();
Printf ("% I64d \ n", ans );
}
}
[Cpp]
// Sum [I] = arr [1] + .. arr [I] ^ 2
// Sum2 [I] = arr [1] ^ 2 + .. arr [I] ^ 2;
// Dp [I] [j] = min {dp [k] [J-1]-sum [I] * sum [k] + (suma [k]-sum [k] ^ 2) /2 + (sum [k] ^ 2-suma [k])/2 };
// Slope optimization 2
# Include <stdio. h>
# Include <string. h>
# Deprecision MAX 1100
# Define INF (1 <30)
# Define int64 _ int64 // long
Struct point {
Int64 x, y;
} Pot [MAX];
Int head, tail, qu [MAX];
Int n, m, arr [MAX];
Int64 sum [MAX], sum2 [MAX], dp [MAX] [MAX];
Void Initial (){
For (int I = 1; I <= n; ++ I ){
Sum [I] = arr [I] + sum [I-1];
Sum2 [I] = arr [I] * arr [I] + sum2 [I-1];
Dp [I] [0] = dp [I-1] [0] + arr [I] * sum [I-1];
}
}
Int CheckIt (point p0, point p1, point p2 ){
Return (p0.x-p1.x) * (p0.y-p2.y)-(p0.y-p1.y) * (p0.x-p2.x) <= 0;
}
Int NotBest (point p0, point p1, int k ){
Return p0.y-k * p0.x> p1.y-k * p1.x;
}
Int Solve_DP (){
Int I, j, k;
For (j = 1; j <= m; ++ j ){
Head = 0, tail = 0;
Qu [tail] = 0;
For (I = j + 1; I <= n; ++ I ){
Pot [I]. x = sum [I-1];
Pot [I]. y = dp [I-1] [J-1] + (sum [I-1] * sum [I-1] + sum2 [I-1])/2;
While (head <= tail-1 &&
CheckIt (pot [qu [tail-1], pot [qu [tail], pot [I]) tail --;
Qu [++ tail] = I;
While (head + 1 <= tail &&
NotBest (pot [qu [head], pot [qu [head + 1], sum [I]) head ++;
K = qu [head];
// Dp [I] [j] = y-k * x + c
Dp [I] [j] = pot [k]. y-sum [I] * pot [k]. x + (sum [I] * sum [I]-sum2 [I])/2;
}
}
Return dp [n] [m];
}
Int GetInt (){
Char ch = '';
While (ch <'0' | ch> '9 ')
Ch = getchar ();
Int x = 0;
While (ch> = '0' & ch <= '9 ')
X = x * 10 + ch-'0', ch = getchar ();
Return x;
}
Int main ()
{
Int I, j, k;
While (scanf ("% d", & n, & m), n + m ){
For (I = 1; I <= n; ++ I)
Scanf ("% d", & arr [I]), sum [I] = arr [I] + sum [I-1];
Initial ();
Int ans = Solve_DP ();
Printf ("% d \ n", ans );
}
}
[Cpp]
// Cost [k + 1] [I] = cost [1] [I]-cost [1] [k]-sum [k] * (sum [I]-sum [k])
// Dp [I] [j] = dp [k] [J-1] + cost [1] [I]-cost [1] [k]-sum [k] * (sum [I]-sum [k])
// = Dp [k] [J-1]-cost [1] [k] + sum [k] ^ 2-sum [I] * sum [k] + cost [1] [I]
// Slope optimization 1
# Include <stdio. h>
# Include <string. h>
# Deprecision MAX 1100
# Define INF (1 <30)
Struct point {
Int x, y;
} Pot [MAX];
Int head, tail, qu [MAX];
Int n, m, arr [MAX], cost [MAX];
Int sum [MAX], sum2 [MAX], dp [MAX] [MAX];
Void Initial (){
For (int I = 1; I <= n; ++ I ){
Sum [I] = arr [I] + sum [I-1];
Cost [I] = cost [I-1] + arr [I] * sum [I-1];
Dp [I] [0] = cost [I];
}
}
Int CheckIt (point p0, point p1, point p2 ){
Return (p0.x-p1.x) * (p0.y-p2.y)-(p0.y-p1.y) * (p0.x-p2.x) <= 0;
}
Int NotBest (point p0, point p1, int k ){
Return p0.y-k * p0.x> p1.y-k * p1.x;
}
Int Solve_DP (){
Int I, j, k;
For (j = 1; j <= m; ++ j ){
Head = 0, tail = 0;
Qu [tail] = 0;
For (I = j + 1; I <= n; ++ I ){
Pot [I]. x = sum [I-1];
Pot [I]. y = dp [I-1] [J-1]-cost [I-1] + sum [I-1] * sum [I-1];
While (head <= tail-1 &&
CheckIt (pot [qu [tail-1], pot [qu [tail], pot [I]) tail --;
Qu [++ tail] = I;
While (head + 1 <= tail &&
NotBest (pot [qu [head], pot [qu [head + 1], sum [I]) head ++;
K = qu [head];
// Dp [I] [j] = y-k * x + c
Dp [I] [j] = pot [k]. y-sum [I] * pot [k]. x + cost [I];
}
}
Return dp [n] [m];
}
Int main ()
{
Int I, j, k;
While (scanf ("% d", & n, & m), n + m ){
For (I = 1; I <= n; ++ I) www.2cto.com
Scanf ("% d", & arr [I]), sum [I] = arr [I] + sum [I-1];
Initial ();
Int ans = Solve_DP ();
Printf ("% d \ n", ans );
}
}