Connection between interval DP and greedy algorithm (uav Cutting Sticks & poj Fence Repair (manual Implementation of HEAP )),
These two questions have the same solution, so we put them together for a summary and comparison to better differentiate the differences between them.
I. interval DP
The Cutting Sticks of uvais is a typical template question.
Description:
There is a wooden stick with a length of l, and there are m cutting points on it. Each cutting will have to pay the price of the current length of the wooden stick, and ask how to cut the minimum price.
Interval DP definition:
The interval dynamic planning problem is generally considered. For each interval, their optimal values are obtained from the Optimal Values of several smaller intervals. It is an application of the divide and conquer idea, divide an interval problem into smaller intervals until the intervals composed of one element, enumerate their combinations, and obtain the optimal value after merging.
Solution:
Set F [I, j] (1 <= I <= j <= n) to represent the minimum cost of adding numbers in the interval [I, j]. The minimum interval is F [I, i] = 0 (a number cannot be merged, cost is 0) each time the range is divided into [I, k] and [k + 1, j]
Interval DP template, code:
For (intp = 1; p <= n; p ++) {// p is the length of the interval and serves as the stage for (int I = 1; I <= n; I ++) {// I is the starting point of the exhaustive interval int j = I + p-1; // j is the end point of the interval for (int k = I; k <j; k ++) // status transfer dp [I] [j] = min {dp [I] [k] + dp [k + 1] [j] + w [I] [j]}; // This is the meaning of the question, some of them start from k, not k + 1 dp [I] [j] = max {dp [I] [k] + dp [k + 1] [j] + w [I] [j] };}}
Solution:
For this question, if we only perform DP on the leftmost cut point and rightmost cut point, the answer is certainly wrong, because it is not the entire interval, therefore, we must add a vertex on the left and right sides of the wooden stick, so we can get the entire interval, and then solve this interval by using DP.
# Include <iostream> # include <algorithm> # include <cstdio> # include <cstring> using namespace std; const int MAXN = 50 + 10; const int INF = ~ 0U> 2; int w [MAXN], dp [MAXN] [MAXN]; int L, n; int solve () {n ++; for (int I = 0; I <= n; ++ I) for (int j = I + 1; j <= n; ++ j) dp [I] [j] = (I + 1 = j? 0: INF); w [0] = 0; w [n] = L; for (int p = 1; p <= n; ++ p) {// Interval Length for (int s = 0; s <= n-p; ++ s) {// start position int e = s + p; // end point for (int k = s + 1; k <e; ++ k) {// status transfer dp [s] [e] = min (dp [s] [e], dp [s] [k] + dp [k] [e] + w [e]-w [s]) ;}} return dp [0] [n];} int main () {while (scanf ("% d", & L), L) {scanf ("% d", & n); for (int I = 1; I <= n; ++ I) {scanf ("% d", & w [I]);} printf ("The minimum cutting is % d. \ n ", solve ();} return 0 ;}
This question of POJ can be viewed as an upper-level version of the upper-level version.
There is no fixed position, the sequence of wood board cutting is uncertain, the degree of freedom is very high, this question seems very difficult to start. But in fact, it can be solved with a slightly strange greedy.
Principle Analysis:
Process Analysis is a binary tree that involves the Harman encoding. Because the analysis process is a bit complex, think about it as a result ). The following algorithm is used to continuously solve the minimum and minimum values in the huffman encoding. Therefore, the simple algorithm is O (N * N ). we can also think of using the priority queue of the binary tree structure to solve the minimum and minimum values. At this time, the time complexity is reduced to O (NlogN ).
# Include <iostream> # include <algorithm> # include <cstdio> # include <cstring> using namespace std; typedef long LL; const int MAXN = 20000 + 10; int N, L [MAXN]; LL solve () {LL ans = 0; // find the minimum value until the while (N> 1) is calculated for a piece of wood, int mii1 = 0, mii2 = 1; if (L [mii1]> L [mii2]) swap (mii1, mii2); for (int I = 2; I <N; ++ I) {if (L [I] <L [mii1]) {mii2 = mii1; mii1 = I ;} else if (L [I] <L [mii2]) {mii2 = I ;}} int t = L [mii1] + L [mii2]; // merge ans + = t; if (mii1 = N-1) swap (mii1, mii2); L [mii1] = t; L [mii2] = L [N-1]; N --;} return ans;} int main () {scanf ("% d", & N); for (int I = 0; I <N; ++ I) {scanf ("% d", & L [I]);} printf ("% lld \ n", solve (); return 0 ;}
Use priority_queue in STL. The time complexity is O (N * logN ).
#include <iostream>#include <algorithm>#include <queue>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;const int MAXN = 20000 + 10;int N,L[MAXN];LL solve(){ LL ans = 0; priority_queue<int,vector<int>,greater<int> > que; for(int i = 0;i < N;++i){ que.push(L[i]); } while(que.size() > 1){ int l1,l2; l1 = que.top(); que.pop(); l2 = que.top(); que.pop(); ans += l1 + l2; que.push(l1+l2); } return ans;}int main(){ scanf("%d",&N); for(int i = 0;i < N;++i){ scanf("%d",&L[i]); } printf("%lld\n",solve()); return 0;}
Use a handwritten heap. Time complexity O (N * logN ).
Stack implementation template:
// Heap implementation int heap [MAXN <2], sz = 0; void push (int x) {// ID of your node int I = sz ++; while (I> 0) {// ID of the parent node int p = (I-1)> 1; // exit if (heap [p] <= x) break if no size is reversed; // put the value of the parent node down, heap [I] = heap [p]; I = p;} heap [I] = x;} int pop () {// minimum int ret = heap [0]; // The value int x = heap [-- sz] of the root to be mentioned; // switch int I = 0 from the root; while (I <1 | 1) <sz) {// compare the son int a = I <1 | 1, B = (I <1) + 2; if (B <sz & heap [B]
Zookeeper