Medicine collection
[Problem description]
Chen is a talented child. His dream is to become the greatest physician in the world. To this end, he wants to worship the most prestigious physicians nearby. In order to judge his qualifications, the physician gave him a difficult problem. The doctor took him to a cave where herbs were everywhere and said to him, "Child, there are some different herbs in this cave. It takes some time to pick every plant, each strain also has its own value. I will give you some time, during which you can collect some herbs. If you are a smart child, you should be able to maximize the total value of collected herbs ." If you are Chen, can you complete this task?
[Input file]
The first line of the input file medic. In contains two positive integers n, m. M indicates the total time that can be used for medicine collection, and N indicates the number of herbs in the cave. Each line of the next n rows contains two integers, indicating the time TI and value VI of a particular herb.
[Output file]
The output file is medic. Out and contains only one integer to indicate the maximum total value of herbs that can be acquired within the specified time.
[Input example]
3 9
10 10
8 1
1 2
[Output example]
3
[Data scale and Conventions]
N, m ≤ 50% of the data;
N, m ≤ 100%, Ti, VI ≤ 10 in 100000 of the data.
If there are n kinds of items, the backpack capacity is m, the item volume, value, maximum number of use is V, W, C, then the simple dynamic rule equation is: f [I] = max {f [I-v * k] + W * k} (1 <= k <= C ). We divide all possible volumes by dividing by the remainder of the current item Volume V into 0 ~ V-1, when the remainder is K (K, [0, V-1]) and can be divided into K, K + v, k + 2 * V... K + J * V... (1 <= j <= (m-k) Div
V) because the transfer of the remainder K only occurs on the several volumes listed above, you can create a monotonic queue for these volumes, in order to quickly find the optimal decision. However, it should be noted that, because the volume and value of these decisions are not the same and there is no comparability between them, we compare the volume of these decisions to K, the unified method only needs to take advantage of the feature that the volume is K + J * V, and subtract the value of F [K + J * V] in the queue from J * w, it is a reference value that can be used for comparison when the volume is K. It is easy to think that, due to the difference between the contribution of the current item and the transfer, this is equivalent to the loss of J * w.
In this way, each time f [K + J * V] is obtained, you only need to find an optimal decision in the queue f [K + j '* V], make J-J' <= C, and maintain the monotonous queue for the rest of the work.
Core code and comments:
Procedure insert (X, Y: longint); // insert to a queue with monotonic decreasing values and increasing frequency
Begin
While (L <= r) and (B [R] <= y) Do Dec (R );
INC (r); A [R]: = x; B [R]: = y;
End;
Begin
Readln (n, m); // n indicates the number of items, and M indicates the size of the backpack.
For I: = 1 to n do
Begin
Read (V, W, c); // read the current item: V indicates the item volume, W indicates the item value, and C indicates the item availability.
If M Div v <C then C: = M Div V; // maximum number of times available
For K: = 0 to V-1 do // divide all the volumes by the remainder of V into 0 ~ V-1
Begin
L: = 1; R: = 0; // clear the queue
For J: = 0 to (m-k) Div V do // K is divided into K, V + k, 2 * V + K... J * V + K...
Begin
Insert (J, F [J * V + k]-J * w); // equivalent to unifying the volume to K and reducing the value by J * w.
While a [l] <j-C do Inc (l); // if the number of deletions exceeds
F [J * V + k]: = B [l] + J * w; // update f [J * V + k] with the value of the queue Header
End;
End;
End;
Writeln (F [m]);
End.
/* Multiple backpacks: the first is binary optimization time complexity O (nmlog2s) and the second is monotonous queue time complexity O (nm) * // method 1 # include <cstdio> # define max (a, B) (a)> (B )? (A) :( B) int DP [100001]; int W [11] [11]; int main () {freopen ("medic. in "," r ", stdin); freopen (" medic. out "," W ", stdout); int n, m; scanf (" % d ", & N, & M); int A, B; for (INT I = 0; I <n; ++ I) {scanf ("% d", & A, & B ); W [a] [B] ++;} For (INT I = 1; I <11; ++ I) // multiple backpacks {for (Int J = 1; j <11; ++ J) {If (! W [I] [J]) continue; If (W [I] [J] * I <m) // 01 backpack {int K = 1; int COUNT = W [I] [J]; while (k <count) // the binary system, processing a bunch of {for (INT v = m; v> = K * I; -- V) DP [v] = max (DP [v], DP [V-K * I] + K * j ); count-= K; K * = 2;} For (INT v = m; V> = count * I; -- V) DP [v] = max (DP [v], DP [V-count * I] + count * j);} else // full backpack {for (INT v = 1; v <= m; ++ V) if (V-I> = 0) DP [v] = max (DP [v], DP [V-I] + J) ;}} int ans = 0; for (INT I = 0; I <= m; ++ I) If (ANS <DP [I]) ans = DP [I]; printf ("% d \ n", ANS); Return 0 ;} /* method 2 # include <cstdio> # define max (a, B) (a)> (B )? (A) :( B) int f [100001]; int WW [11] [11]; int L, R; int A [100001]; int B [100001]; inline void insert (int x, int y) {While (L <= R & B [R] <= y) r --; ++ R; A [R] = x; B [R] = y;} int main () {freopen ("medic. in "," r ", stdin); freopen (" medic. out "," W ", stdout); int n, m; scanf (" % d ", & N, & M); // M indicates the backpack capacity int CC, dd; int sum = 0; For (INT I = 0; I <n; ++ I) {scanf ("% d", & CC, & DD ); WW [CC] [DD] ++;} For (INT I = 1; I <11; ++ I) for (Int J J = 1; JJ <11; ++ JJ) {If (! WW [I] [JJ]) continue; // process each item int c = I; // the consumption of the item int W = JJ; // item value int n = WW [I] [JJ]; // number of items if (M/C <n) n = M/C; // maximum number of times available for (int K = 0; k <= C-1; ++ K) // divide all the volumes by the remainder of V to 0 ~ V-1 {L = 1; r = 0; // clear the queue for (Int J = 0; j <= (m-k)/C; ++ J) // if the remainder is K, K, V + k, 2 * V + K... J * V + K... {// Insert (J, F [J * C + k]-J * w); // equivalent to unifying the volume to K, value minus J * w, in this case, int x = J; int y = f [J * C + k]-J * W; while (L <= R & B [R] <= y) r --; ++ R; A [R] = x; B [R] = y; while (A [l] <(J-N) ++ L; // F [J * C + k] = B [l] + J * w whose number of deletions exceeds N; // update f [J * C + k]} printf ("% d \ n", F [m]); Return 0 ;}*/