The problem needs to use data structure to optimize DP, the specific method is described in the eighth chapter (using Data structure optimization algorithm, purple book P241), using an array and two pointers to maintain a monotone queue, can be in O (n) time to find the minimum value of the sliding window.
With this optimization we can quickly find the minimum value of dp[i-1][j] (x-d<=j<=x+d).
However, Rujia did not do so, he only used a pointer, even the maintenance Priority queue array is not open, the "implicit" to find the minimum value.
The specific approach is:
1. First maintain the window left edge, do not let the pointer k out of the window, if X[K] < x[j]-D then k++ (because the x array is from large to small already ordered), and then not beyond the right edge x[j]+d, if dp[i][k+1] <= dp[i][k], So k++;
Why is this right? It seems that the priority queue is not the same as before! In fact, the same operation, carefully recall how to maintain the priority queue is how to operate: with two pointers front, rear first update the left edge, to prevent him from exceeding the boundary, once out of the front++; and then each time a new value is added to see the current queue at the far right of the element and the new value of the size, If it is greater than the new value then rear--, the useless elements out of the queue, until less than the new value, the new value is added, however, in fact, the top of the method with a pointer is the same, but will delete the useless value of this step to the minimum value, that is, update K.
Through this problem, we have a new understanding of the priority queue to find the interval minimum value, and have a deeper understanding of this ingenious construction method. It is also worth mentioning that the small sliding window has a lot of deformation, sometimes the size of the window is still variable. How to optimize, how to maintain, but also to go through the purple book slowly experience.
#include <bits/stdc++.h>using namespace Std;typedef long long ll;const int MAXN = + 5;const int maxx = maxn*maxn* 2;const ll INF = (1ll <<), int t,n,d;ll H[maxn],x[maxx],dp[2][maxx];int main () {scanf ("%d", &t); while (t--) {scanf ("%d%d", &n,&d); for (int i=0;i<n;i++) scanf ("%lld", &h[i]); if (ABS (H[0]-h[n-1]) > (n-1) *d) {//This way, at least two points in any case are more than D printf ("impossible\n"); continue; } int nx = 0; for (int i=0;i<n;i++) for (int j=-n+1;j<=n-1;j++) x[nx++] = H[i] + j*d; First, all possible situations are taken out, sorted, de-weighed, easy to organize priority queue sort (X,X+NX); NX = Unique (X,X+NX)-X; int t = 0; for (int i=0;i<=nx;i++) {Dp[0][i] = INF; if (x[i] = = H[0]) dp[0][i] = 0; Boundary processing Dafa} for (int i=1;i<n;i++) {int k = 0; for (int j=0;j<nx;j++) {while (K < NX && X[k] < x[j]-d) k++; while (K+1 < NX && X[k+1] <= x[j]+d && dp[t][k+1] <= dp[t][k]) k++; Use the priority queue to find the minimum value if (dp[t][k] = = inf) dp[t^1][j] = inf; else dp[t^1][j] = Dp[t][k] + ABS (X[J]-h[i]); } t ^= 1; Save memory with scrolling array} for (int i=0;i<nx;i++) if (x[i] = = H[n-1]) {printf ("%lld\n", Dp[t][i]); break; }} return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
12170-easy Climb (dp+ monotone queue)