Special analysis of algorithm competition (12): DP optimization (2)-slope (convex hull) optimization

This series is an extension of this algorithm textbook: "Introduction to Advanced Algorithm Contest" ( Jingdong Dangdang ) Tsinghua University Press
If you have any suggestions, please contact: (1) QQ Group, 567554289; (2) Author QQ, 15512356

  There is a class of DP equations of state, for example:
    \ (dp [i] = min \ {dp [j]-a [i] * d [j] \} \)    \ (0≤j <i, d [j] ≤d [j + 1], a [
i] ≤ a [i + 1] \)   which is characterized by the presence of both a \ (I \) have \ (J \) term \ (a [i] * d [ j] \) .
  When programming, if you simply loop through \ (i \) and \ (j \) , the complexity is \ (O (n ^ 2) \) .
  Through slope optimization (convex hull trick, convex hull optimization), the time complexity is optimized to \ (O (n) \) .
  The core technology of slope optimization is the slope (convex hull) model and monotonous queue.

1. Transform the equation of state into a plane slope problem

  The equation finds the optimal value of \ (dp [i] \) when \ (j \) changes for a fixed \ (i \) , so the part about \ (i \) can be regarded as a fixed value, and The part about \ (j \) is regarded as a variable. The \ (min \) is removed, the equation into: \ (DP [J] = A [I] * D [J] + DP [I] \)   for the convenience of observation, so that: \ (Y = DP [J] \ ) , \ (X = d [j] \) , \ (k = a [i] \) , \ (b = dp [i] \) , the equation becomes: \ (y = kx + b \)   slope optimization The mathematical model of is to convert the state transfer equation to a straight line in the plane coordinate system: \ (y = kx + b \) . Among them:   (1) The variables \ (x \) , \ (y \) and \ (j \) are related, and only \ (y \) contains \ (dp [j] \) . The point \ ((x, y) \) is a possible decision in the question.
    

    


  (2) The slope \ (k \) and intercept \ (b \) are related to \ (i \) , and only \ (b \) contains \ (dp [i] \) . The smallest \ (b \) contains the smallest \ (dp [i] \) , which is the solution of the equation of state.
  Note the 2 conditions for applying slope optimization: \ (x \) and \ (k \) increase monotonously, ie \ (x \) increases with \ (j \) , \ (k \) follows \ (i \) increments and increments.

2. Find a dp [i]

  Consider first finding \ (dp [i] \) when fixed \ (i \) . Since \ (i \) is a fixed value, the slope \ (k = a [i] \) can be regarded as a constant. When \ (J \) in \ (0≤j <i \) when the change of a \ (j_r \) , generating a point \ (V_R = (x_r, Y_r) \) , at this point in a straight line \ (y = kx + b_r \) , \ (b_r \) is the intercept. Figure 1.

Figure 1 Line passing through point (x, y)

  For \ (0≤j <i \) in all \ (J \) , to their corresponding points are drawn on the plane, the slope of the line corresponding to the point \ (k = a [i] \) are the same, Only the intercept \ (b \) is different. Among all these points, there is a point \ (v '\) where the straight line has the smallest intercept \ (b' \) , calculate \ (b '\) , because \ (b' \) contains \ (dp [ i] \) , then the optimal \ (dp [i] \) is calculated . As shown in Figure 2.

Figure 2 The straight line passing through the most advantageous v '

  How to find the most advantageous \ (v '\) ? Use the "lower convex shell".
  As mentioned earlier, \ (x \) increases monotonically, that is, \ (x \) increases with \ (j \) . Four points are given in Figure 3 (1), and their \ (x \) coordinates are increasing.

(1) Original picture (2) Remove point 3 (3 Find the optimal v 'point
Figure 3 Use the lower convex shell to find the best advantage

  1, 2, and 3 in FIG. 3 (1) constitute a "lower convex hull". The characteristic of the "lower convex hull" is that the slope of the line segment 12 is smaller than the slope of the line segment 23. 2, 3, 4 constitute the "upper convex shell". The intercept b of the straight line passing through the middle point 3 of the upper convex hull must be smaller than the intercept of the straight line passing through 2 or 4 with the same slope, so point 3 is definitely not the best advantage, and remove it.
  After removing the "upper convex hull", we get Figure 3 (2), and all the remaining points satisfy the "lower convex hull" relationship. The best advantage lies in the "lower convex shell". For example, in Figure 3 (3), cut these points with a straight line with a slope of \ (k \) . If the slope of line segment 12 is smaller than \ (k \) and the slope of 24 is larger than \ (k \) , then point 2 is The most advantage of "lower convex shell".
  The above operation is very convenient to use monotonous queue programming.
  (1) Entering the team, maintaining a "lower convex hull" in the queue, that is, a straight line composed of every 2 consecutive points, whose slope is monotonously rising. When a new point is entered into the queue, make sure that it can still form a "lower convex hull" along with the points in the queue. For example, the two points at the end of the queue are \ (v_1 \) , \ (v_2 \) , and the new point to be added to the queue is \ (v_3 \) . Compare \ (v_1 \) , \ (v_2 \) , \ (V_3 \) , look at the line \ (v_1v_2 \) and \ (v_2v_3 \) whether the slope is incremented, and if so, \ (v_1 \) , \ (v_2 \) ,\ (v_3 \) forms a "lower convex hull"; if the slope does not increase, it means that \ (v_2 \) is wrong, bounce it off the tail of the team; then continue to compare the 2 points at the tail of the queue and \ (v_3 \) ; repeat The above operation until \ (v_3 \) can enter the team. After the above operations, the points in the queue form a large "lower convex hull". The straight line formed by each 2 points has an increasing slope, and the queue remains a monotonous queue.
  (2) Get out of the queue and find the best advantage. The two points at the head of the team are \ (v_1 \) and \ (v_2 \) . If the slope of the line segment \ (v_1v_2 \) is smaller than \ (k \) , it means that \ (v_1 \) is not the best advantage, bounce it away continue comparing the new team points head 2 until the slope is greater than \ (K \) , at which time point is the most advantage HOL \ (V '\) .

3. Find all dp [i]

  The above obtained a \ (dp [i] \) , complexity \ (O (n) \) . If all \ (I \) , each such request \ (DP [I] \) , the overall complexity is still \ (O (n ^ 2) \) , and the computational complexity does not change. Is there an optimized method?
  A smaller \ (i_1 \) , its corresponding point is { \ (v_0, v_1, ..., v_ {i1} \) }; a larger \ (i_2 \) corresponds to more points { \ (v_0, v_1, ..., v_ {i1}, ..., v_ {i2} \) }, which contains all the points of \ (i_1 \) . When looking for the best advantage of \ (i_1 \) , you need to check { \ (v_0, v_1, ..., v_ {i1} \) }; when looking for the best advantage of i2, you need to check { \ (v_0, v_1,. .., v_ {i1}, ..., v_ {i2} \) }. Duplicate checks are made here, and these duplications can be avoided. This is where it can be optimized, and still use the "lower convex shell" for optimization.
  (1) The slope corresponding to each \ (i \) \ (k_i = a [i] \) is different, according to the constraints\ (a [i] ≤ a [i + 1] \) , when \ (i \) increases, the slope increases.

Figure 4 Lines corresponding to multiple i

  (2) As mentioned earlier, when you find the best point of a \ (i_1 \) , you can remove some points, that is, those with a slope smaller than \ (k_ {i1} \) . These removed points, when the larger \ (i_2 \) in the back , because the slope \ (k_ {i2} \) is also larger, it must be removed.
  According to the discussion of (1) and (2), the optimization method is: for all \ (i \) , use a monotonous queue to handle all points in a unified manner; the points removed by the smaller \ (i_1 \) are monotonically queued Bounce away, the larger \ (i_2 \) at the back no longer processes them.
  Because each point only enters the monotonous queue once, the total complexity is \ (O (n) \) .
  The following code demonstrates the above operation.

//q[]是单调队列,head指向队首,tail指向队尾,slope()计算2个点组成的直线的斜率
for(int i=1;i<=n;i++){ 
    while(head<tail && slope(q[head],q[head+1])<k)  //队头的2个点斜率小于k 
        head++;                                     //不合格,从队头弹出
    int j = q[head];   //队头是最优点
    dp[i] = ...;       //计算dp[i]
    while(head<tail && slope(i,q[tail-1])<slope(q[tail-1],q[tail]))   //进队操作
        tail--;        //弹走队尾不合格的点
    q[++tail] = i;     //新的点进队列
}

  To deepen the understanding of the above code, consider a special case: the points entering the queue all conform to the "lower convex hull" feature, and the slope of the straight line formed by these points is greater than all the slopes \ (k_i \) , then the result is: the team head does not It will be ejected, the points entering the team will not be ejected, and the team head will be reused \ (n \) times.

Figure 5 A special case

4. Examples

  A typical example is given below with a sample question.


HDU 3507 Print Article http://acm.hdu.edu.cn/showproblem.php?pid=3507
Topic description : Print an article containing N words, the printing cost of the i-th word is Ci. The cost of printing k words in one line is that M is a constant. How to arrange articles to minimize costs?
Input : There are many test cases. For each test case, there are two numbers N and M in the first row (0≤n≤500000, 0≤M≤1000). Then, there are N numbers in the next 2 to N + 1 rows. Input is terminated with EOF.
Output : A number indicating the minimum cost of printing the article.
Sample input :
5 5
5
9
5
7
5
Sample output :
230


  The meaning of the title is: there are \ (N \) numbers and a constant \ (M \) , the \ (N \) number is divided into several parts, and the calculated value of each part is the square of the sum of these parts plus \ (M \) , the total calculated value is the sum of the calculated values ​​of all parts, and find the smallest total calculated value. Since \ (N \) is large, the algorithm of \ (O (N ^ 2) \) times out.
  Let \ (dp [i] \) denote the minimum cost of \ (i \) words before output , DP transfer equation:
    \ (dp [i] = min \ {dp [j] + (sum [i] -sum [ j]) 2 + M \} \)    \ (0 <j <i \)
  where \ (sum [i] \) represents the sum of the first \ (i \) digits.
  The following rewrites the DP equation as \ (y = kx + b \) . First expand the equation:
    \ (dp [i] = dp [j] + sum [i] * sum [i] + sum [j] * sum [j]-2 * sum [i] * sum [j] + M \ )
  Move items:
    \ (dp [j] + sum [j] * sum [j] = 2 * sum [i] * sum [j] + dp [i] -sum [i] * sum [i]-M \)
  Control\ (y = kx + b \) , there are:
  \ (y = dp [j] + sum [j] * sum [j] \) , \ (y \) is only related to \ (j \) .
  \ (x = 2 * sum [j] \) , \ (x \) is only related to \ (j \) , and increases with the increase of \ (j \) .
  \ (k = sum [i] \) , \ (k \) is only related to \ (j \) , and increases as \ (i \) increases.
  \ (b = dp [i]-sum [i] * sum [i]-M \) , \ (b \) is only related to i, and contains \ (dp [i] \) .
  The code is given below.

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500010;

int dp[MAXN];   
int q[MAXN];      //单调队列
int sum[MAXN];

int X(int x){ return 2*sum[x]; }
int Y(int x){ return dp[x]+sum[x]*sum[x]; }
//double slope(int a,int b){return (Y(a)-Y(b))/(X(a)-X(b));} //除法不好,改成下面的乘法
int slope_up  (int a,int b) { return Y(a)-Y(b);}   //斜率的分子部分
int slope_down(int a,int b) { return X(a)-X(b);}   //斜率的分母部分

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++)  scanf("%d",&sum[i]);
        sum[0] = dp[0] = 0;
        for(int i=1;i<=n;i++)  sum[i]+=sum[i-1];

        int head=1,tail=1;      //队头队尾
        q[tail]=0;
        for(int i=1;i<=n;i++){
            while(head<tail &&
                  slope_up(q[head+1],q[head])<=sum[i]*slope_down(q[head+1],q[head])) 
               head++;           //斜率小于k,从队头弹走

            int j = q[head];     //队头是最优点
            dp[i] = dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);    //计算dp[i]

            while(head<tail && 
                              slope_up(i,q[tail])*slope_down(q[tail],q[tail-1])
                           <= slope_up(q[tail],q[tail-1])*slope_down(i,q[tail]))
                tail--;          //弹走队尾不合格的点
            q[++tail] = i;       //新的点进队尾
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}

5. Exercises

  (1) Luogu P3195 toy packing https://www.luogu.com.cn/problem/P3195
  DP equation: \ (dp [i] = min \ {dp [j] + (sum [i] + i− sum [j] −j−L−1) ^ 2 \} \)
  
  (2) Luogu 4072 SDOI2016 journey https://www.luogu.com.cn/problem/P4072
  Two-dimensional slope optimization, DP equation: \ ( dp [i] [p] = min \ {dp [j] [p−1] + (s [i] −s [j]) ^ 2 \} \)

Guess you like

Origin www.cnblogs.com/luoyj/p/12714103.html