Test instructions: N items with weights and values of Wi,vi respectively. From these items, select items with a total weight of not more than W, and ask for the maximum value of the sum of the values in all selection scenarios.
Restrictions:
1 <= N <= 40
1 <= WI, vi <= 10 of 15 power
1 <= W <= 10 15 Power
Input:
n = 4
W = {2, 1, 3, 2}
v = {3, 2, 4, 2}
W = 5
Output:
7 (pick items 0, 1, 3rd)
Analysis:
This question is the knapsack problem described earlier, but this time the value and weight can be very large values, compared to n is relatively small. The complexity of solving knapsack problems with DP is O (NW), and therefore cannot be used to solve the problem here.
We can split the previous question into two halves and then enumerate it, because each part is only 20, so it is possible. Using the value and weight of the two halves after splitting, we can find the original problem.
We recorded the sum of weights and values in the first half of the selection method as W1, v1. So in the latter part of the total weight W2 <= w-w1 to make the V2 the largest selection method is good.
Therefore, we want to consider the method of efficiently finding max{v2|w2<= W '} from the collection of enumerations (W2, V2). First of all, obviously we can exclude all W2[i] <= w2[j] and V2[i] >= V2[j] J. This can be done simply by W2, V2 dictionary ordering. Then the remaining elements satisfy W2[i] < W2[j]===v2[i] < V2[j], to calculate max{v2|w2<= W '}, just look for the largest I to meet W2[i] <= W. This can be done with a two-point search.
#include <cstdio> #include <algorithm> #include <map> #include <vector>using namespace std; typedef long LONG Ll;const int MAXN = + 5;const int INF = 10000000;int n;ll w[maxn], v[maxn];ll w;pair<ll, ll> PS [1 << (MAXN/2)]; (weight, value) void Solve () {//enum first half int n2 = N/2; for (int i = 0; i < 1 << n2; i++) {ll sw = 0, SV = 0; for (int j = 0; J < N2; J + +) {if (i >> J & 1) {SW + = W[i]; SV + = V[i]; }} Ps[i] = Make_pair (SW, SV); }//Remove excess elements sort (PS, PS + (1 << n2)); int m = 1; for (int i = 1; i < 1 << n2; i++) {if (Ps[m-1].second < Ps[i].second) {ps[m++] = ps[i]; }}//Enumerate the latter half and solve ll res = 0; for (int i = 0; i < 1 << (N-N2); i++) {ll sw = 0, SV = 0; for (int j = 0; J < N-n2; J + +) {if (i >> J & 1) {SW + = W[n2 + J]; SV + = v[n2 + j]; }} if (sw <= W) {ll TV = (Lower_bound (PS, PS + M, Make_pair (W-SW, INF))-1), second; res = max (res, SV + TV); }} printf ("%lld\n", res);}
Oversized knapsack problem (binary enumeration)