Quadrilateral optimized dp
------------------------------------
The most expensive value is represented by d [I, j ].
D [I, j] = min {d [I, k-1] + d [k + 1, j]} + w [I, j]
W [I, j] = sum [I, j]
Quadrilateral Inequality
W [a, c] + w [B, d] <= w [B, c] + w [a, d] ( Monotonic decision
W [I, j] <= w [I ', J'] ([I, j] belongs to [I', J '])
So we have the following three theorems:
Theorem 1: If w satisfies both the Quadrilateral inequality and the monotonicity of decision-making, d also satisfies the Quadrilateral inequality.
Theorem 2: when the condition of Theorem 1 is met, let d [I, j] Take k of the minimum value as K [I, j], then K [I, j-1] <= K [I, j] <= K [I + 1, j]
Theorem 3: w is convex and only when w [I, j] + w [I + 1, j + 1] <= w [I + 1, j] + w [I, j + 1]
Judging whether a w is convex means judging whether the value of w [I, j + 1]-w [I, j] decreases with the increase of I.
So K [I, j] is only related to K [I + 1, j] and K [I, J-1] When K is obtained, therefore, we can use the ascending I-j order to recursively calculate the final result of each state value and convert O (n ^ 3) to O (n ^ 2)
Certificate --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Note:
Pay attention to the monotonic order of decision-making, which must be consistent with the decision tonality and meaning (!!!!)
Pay attention to the enumeration order. Based on the dp equation and the monotonic equation of decision-making
Pay attention to initialization to prevent access to the invalid or unprocessed status. Initialize the dp and s boundaries, especially the last and next stages of decision-making.
Example 1:
Sharding problem: hdu 3506
Dp [I] [j] = min {dp [I] [k] + dp [k + 1] [j] + cost [I, j]}, I <= k <= j-1, cost [I] [j] = sum [j]-sum [I-1]
S [I] [j-1] <= s [I] [j] <= s [I + 1] [j]
// # Pragma warning (disable: 4786) // # pragma comment (linker,/STACK: 16777216) // HEAD # include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include using namespace std; // LOOP # define FE (I, a, B) for (int I = (a); I <= (B); ++ I) # define FD (I, B, a) for (int I = (B); I >= (a); -- I) # define REP (I, N) for (int I = 0; I <(N); ++ I) # define CLR (A, value) memset (A, value, sizeof ()) # define CPY (a, B) memcpy (a, B, sizeof (a) # define FC (it, c) for (_ typeof (c ). begin () it = (c ). begin (); it! = (C ). end (); it ++) // INPUT # define RI (n) scanf (% d, & n) # define RII (n, m) scanf (% d, & n, & m) # define RIII (n, m, k) scanf (% d, & n, & m, & k) # define RS (s) scanf (% s, s) // OUTPUT # define WI (n) printf (% d, n) # define WS (s) printf (% s, s) typedef long LL; const int INF = 1000000007; const double eps = 1e-10; const int maxn = 2010; int dp [maxn] [maxn], s [maxn] [maxn]; int w [maxn] [maxn]; int n, m; int val [maxn]; int sum [Maxn]; // obtain the minimum dp value // The enumerated range ranges from small to large void solve () {// memset (dp, 0, sizeof (dp )); /// initialization invalid value FE (I, 1, 2 * n) {dp [I] [I] = 0; s [I] [I] = I; /// initialization decision next session, 0} FE (len, 2, n) {for (int I = 2 * n-len; I> = 1; I --) {int j = I + len-1; dp [I] [j] = INF; int a = s [I] [j-1], B = s [I + 1] [j]; int cost = sum [j]-sum [I-1]; for (int k = a; k <= B; k ++) {if (dp [I] [j]> dp [I] [k] + dp [k + 1] [j] + cost) {dp [I] [j] = dp [I] [k] + dp [k + 1] [j] + cost; s [I] [j] = k ;}}} int main () {while (~ RI (n) {FE (I, 1, n) RI (val [I]), val [I + n] = val [I]; FE (I, 1, 2 * n) sum [I] = sum [I-1] + val [I]; // pre (); solve (); int ans = INF; FE (I, 1, n) {if (ans> dp [I] [n + I-1]) ans = dp [I] [n + I-1];} printf (% d, ans);} return 0 ;}
Example 2: Post Office problems:
Poj 1160
1: note that the order of I and j in this method is different from that in normal cases.
The decision interval is: s [I-1] [j] <= s [I] [j] <= s [I] [j + 1] (!).
For details, see notes:
// # Pragma warning (disable: 4786) // # pragma comment (linker,/STACK: 16777216) // HEAD # include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include using namespace std; // LOOP # define FE (I, a, B) for (int I = (a); I <= (B); ++ I) # define FD (I, B, a) for (int I = (B); I >= (a); -- I) # define REP (I, N) for (int I = 0; I <(N); ++ I) # define CLR (A, value) memset (A, value, sizeof ()) # define CPY (a, B) memcpy (a, B, sizeof (a) # define FC (it, c) for (_ typeof (c ). begin () it = (c ). begin (); it! = (C ). end (); it ++) // INPUT # define RI (n) scanf (% d, & n) # define RII (n, m) scanf (% d, & n, & m) # define RIII (n, m, k) scanf (% d, & n, & m, & k) # define RS (s) scanf (% s, s) // OUTPUT # define WI (n) printf (% d, n) # define WS (s) printf (% s, s) typedef long LL; const int INF = 1000000007; const double eps = 1e-10; const int maxn = 1000010; int dp [33] [333], s [33] [333]; int w [333] [333]; int n, m; int val [333]; int sum [333];/ // Dp [I] [j] = min {dp [I-1] [k] + w [k + 1] [j]}, i-1 <= k <= j-1 // General requirements I <= j (!!) // S [I-1] [j] <= s [I] [j] <= s [I] [j + 1] (!) /// Pay attention to the monotonic order of decision-making, which must be consistent with the decision tonality and meaning (!!!!) /// Pay attention to the enumeration order, and initialize Based on the dp equation and the monotonic equation of decision. // pay attention to initialization to prevent access to invalid or unprocessed states. Initialize the dp and s boundaries, especially the last and next stages of decision-making. Void pre () {for (int I = 1; I <= n; I ++) // here is a recursive formula for preprocessing {w [I] [I] = 0; for (int j = I + 1; j <= n; j ++) {int mid = (j + I)> 1; w [I] [j] = w [I] [j-1] + val [j]-val [mid]; // int x = sum [j]-sum [mid]-val [mid] * (j-mid ); // x + = val [mid] * (mid-I)-(sum [mid-1]-sum [I-1]) ;}} /// obtain the minimum dp value // enumerate I from small to large // then enumerate j from large to small void solve () {memset (dp, 0, sizeof (dp); // initialize the invalid FE (I, 1, n) {dp [1] [I] = w [1] [I]; s [1] [I] = 0; // initialization decision next, 0} FE (I, 2, m) {// s [1] [I] = 0; s [I] [n + 1] = n; // initialize the previous decision for (int j = n; j> = I; j --) {int tmp = dp [I] [j] = INF; // initialize the optimal value int a = s [I-1] [j], B = s [I] [j + 1]; // a = max (a, I-1); B = min (B, j-1 ); // I-1 <= k <= j-1 for (int k = a; k <= B; k ++) // ensure that all enumerated values are valid, {if (tmp> dp [I-1] [k] + w [k + 1] [j]) {tmp = dp [I-1] [k] + w [k + 1] [j]; s [I] [j] = k ;}} Dp [I] [j] = tmp ;}} int main () {while (~ RII (n, m) {FE (I, 1, n) RI (val [I]), sum [I] = sum [I-1] + val [I]; pre (); solve (); printf (% d, dp [m] [n]);} return 0 ;}
2:-For details, see annotations.
The decision interval is: s [I] [j-1] <= s [I] [j] <= s [I + 1] [j] (!).
// # Pragma warning (disable: 4786) // # pragma comment (linker,/STACK: 16777216) // HEAD # include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include using namespace std; // LOOP # define FE (I, a, B) for (int I = (a); I <= (B); ++ I) # define FD (I, B, a) for (int I = (B); I >= (a); -- I) # define REP (I, N) for (int I = 0; I <(N); ++ I) # define CLR (A, value) memset (A, value, sizeof ()) # define CPY (a, B) memcpy (a, B, sizeof (a) # define FC (it, c) for (_ typeof (c ). begin () it = (c ). begin (); it! = (C ). end (); it ++) // INPUT # define RI (n) scanf (% d, & n) # define RII (n, m) scanf (% d, & n, & m) # define RIII (n, m, k) scanf (% d, & n, & m, & k) # define RS (s) scanf (% s, s) // OUTPUT # define WI (n) printf (% d, n) # define WS (s) printf (% s, s) typedef long LL; const int INF = 1000000007; const double eps = 1e-10; const int maxn = 1000010; int dp [333] [33], s [333] [33]; int w [333] [333]; int n, m; int val [333]; int sum [333];/ // Dp [I] [j] = min {dp [k] [j-1] + w [k + 1] [j]}, j-1 <= k <= I-1 // here I> = j // s [I] [j-1] <= s [I] [j] <= s [I + 1] [j] (!) /// Pay attention to the monotonic order of decision-making, which must be consistent with the decision tonality and meaning (!!!!) /// Pay attention to the enumeration order, and initialize Based on the dp equation and the monotonic equation of decision. // pay attention to initialization to prevent access to invalid or unprocessed states. Initialize the dp and s boundaries, especially the last and next stages of decision-making. Void pre () {for (int I = 1; I <= n; I ++) // here is a recursive formula for preprocessing {w [I] [I] = 0; for (int j = I + 1; j <= n; j ++) {int mid = (j + I)> 1; w [I] [j] = w [I] [j-1] + val [j]-val [mid] ;}} /// obtain the minimum dp value // enumerate I from small to large // then enumerate j from large to small void solve () {memset (dp, 0, sizeof (dp); // initialize the invalid FE (I, 1, n) {dp [I] [1] = w [1] [I]; s [I] [1] = 0; // initialization decision next time, 0} FE (I, 2, m) {// s [I] [1] = 0; s [n + 1] [I] = n; // initialize the previous decision for (int j = n; j> = I; j --) {int tmp = dp [j] [I] = INF; // initialize the optimal value int a = s [j] [I-1], B = s [j + 1] [I]; // a = max (a, I-1); B = min (B, j-1 ); for (int k = a; k <= B; k ++) // ensure that all enumerated values are valid, {if (tmp> dp [k] [I-1] + w [k + 1] [j]) {tmp = dp [k] [I-1] + w [k + 1] [j]; s [j] [I] = k ;}} dp [j] [I] = tmp ;}} int main () {while (~ RII (n, m) {FE (I, 1, n) RI (val [I]); pre (); solve (); printf (% d, dp [n] [m]);} return 0 ;}
Certificate ------------------------------------------- certificate --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Then, the decision interval is s [I-1] [j] <= s [I] [j] <= s [I] [j + 1] (!).