Reprinted please indicate the source: Thank you
Http://user.qzone.qq.com/289065406/blog/1304489412
General question:
A farmer wants to crop a board into several small boards with a given length. Each saw is charged for the length of the current wood board.
The minimum cost is calculated based on the length of each sub-board and the number n of sub-boards.
Tip:
To
3
5 8 5 For example:
First saw a 21-length wooden board from an infinitely long wooden board, and spent 21
Then, we saw 5 boards from a wooden board with a length of 21 and spent 5
Then, we saw 8 boards from a 16-length board and spent 8
Total cost = 21 + 5 + 8 = 34
Solution:
Using the Huffman idea, to minimize the total cost, you can only add the two boards with the minimum length each time, and then add the "and" to the total cost.
Although this question uses the Huffman idea, it will time out to directly use the huffmantree. You can use the priority queue to do it.
Because the simple huffmantree idea is:
(1) Sort all input elements in ascending order, and then select the smallest two elements to accumulate their values to the total cost.
(2) Move the two smallest elements out of the queue, their values into the queue, re-arrange all elements, and repeat (1) until the number of elements in the queue <= 1, the cumulative fee is the minimum fee.
The reason why the huffmantree times out is that it will be re-ordered every time, which is a waste of time, even if it is fast.
An Optimized Solution is:
(1) only sort all data in ascending order (not sort later)
(2) The queue pointer P points to the queue's 1st elements, then retrieves the first two elements of the queue, and accumulates their values to the total cost, insert the sum value as a new element into the proper position of the queue.
Because the first two elements of the original queue have been taken out, the two locations are discarded. We can use the last element position during the insert operation to put the queue pointer p + 1 first, point him to the position of 2nd discarded elements, and then compare sum from 3rd to each element one by one. If sum is greater than this element, the element is moved one by one, otherwise, sum inserts the previous position of the currently being compared element (the first element in the queue is greater than or equal to sum ).
(3) Repeat the preceding operations to start the new queue at the position of the current p.
Another method is to use STL's priority queue, priority_queue, which is very convenient, simple, and efficient. Although the basic theoretical idea of priority_queue is still the above optimization idea, however, STL can directly implement these operations using related function functions, which is relatively simple. For details, see my program.
Note that the values returned by the comparison rules of priority_queue and qsort are the opposite.
Appendix:
Source correction:
Test data http://ace.delos.com/TESTDATA/NOV06_4.htm
The test data shows that there is a large number. Use _ int64
/* Priority queue * // memory time // 376 K 516 Ms # include <iostream> using namespace STD; int CMP (const void * a, const void * B) {return * (int *) A-* (int *) B;} int main (void) {int N; while (CIN> N) {__ int64 * w = new _ int64 [n + 1]; // The value of each piece of wood for (INT p = 1; P <= N; P ++) scanf ("% i64d", & W [p]); qsort (W, n + 1, sizeof (_ int64), CMP) ;__ int64 mincost = 0; for (INT I = 1; I <= n-1; I ++) // each time you enumerate the first two (minimum) elements of the remaining series, then I to n-1 can be {__int64 sum = W [I] + W [I + 1]; // at this time, mincost + = sum; For (Int J = I + 2; j <= N; j ++) is no longer used for W [I] and w [I + 1) // find W [I] + W [I + 1], that is, the proper position of sum in the remaining series, and insert {If (sum> W [J]) // sum is greater than the current element {W [J-1] = W [J]; // The current element moves forward to a grid if (j = N) // sum is greater than the last element (that is, greater than all elements) {W [J] = sum; // insert to the last break;} else {W [J-1] = sum; // insert it to break before the first element greater than sum (previous elements are moved forward); }}printf ("% i64d \ n", mincost );} return 0 ;}
============ Gorgeous split line ======================
/* STL priority queue * // memory time // 512 K 47 Ms # include <iostream> # include <vector> # include <queue> using namespace STD; // comparison rule, minimum priority class CMP {public: bool operator () (const _ int64 A, const _ int64 B) const {return A> B ;}}; int main (void) {int N; // number of boards to be cut while (CIN> N) {priority_queue <__ int64, vector <__ int64>, CMP> queue; // define the priority queue for (INT I = 1; I <= N; I ++) {__ int64 temp; scanf ("% i64d", & temp); queue. push (temp); // enter the required length (cost) and join the team} _ Int64 mincost = 0; // minimum fee while (queue. size ()> 1) // when the queue is smaller than or equal to one element, it jumps out of {__int64 A = queue. top (); // obtain the value of the first element of the queue and queue it out. pop () ;__ int64 B = queue. top (); // get the first line twice, that is, get the minimum two values queue. pop (); queue. push (a + B); // enter mincost + = a + B;} printf ("% i64d \ n", mincost); While (! Queue. Empty () // clear the queue. Pop () ;}return 0 ;}
============ Gorgeous split line ======================
/* Simple idea ---> TLE */# include <iostream> using namespace STD; const _ int64 INF = 1e18; int CMP (const void * a, const void * B) {return * (int *) A-* (int *) B;} int main (INT p) {int N; while (CIN> N) {__ int64 * w = new _ int64 [2 * n]; // The value of each piece of wood for (INT I = 0; I <2 * n; I ++) W [I] = inf; For (P = 0; P <n; P ++) scanf ("% i64d", & W [p]); int mincost = 0; while (true) {qsort (W, 2 * n, sizeof (_ int64), CMP); If (W [1] = inf) break; W [p] = W [0] + W [1]; W [0] = W [1] = inf; mincost + = W [p ++];} cout <mincost <Endl; Delete W;} return 0 ;}