Huge backpack problems: There are n items with weight and value W [I] and V [I] respectively. From these items, select items with a total weight of no more than W, calculate the maximum value of all selected solutions. Where, 1 ≤ n ≤ 40, 1 ≤ W [I], V [I] ≤ 10 ^ 15, 1 ≤ W ≤ 10 ^ 15.

This problem gives people the first impression that they are ordinary 01 backpacks. However, after reading the data range, we will find that both the value and the weight can be very large, and N is relatively small. The complexity of using DP to solve a backpack is O (NW), so it cannot be used to solve this problem. In this case, we should use N to find other methods.

There are a total of 2 ^ n options for selecting items, so you cannot enumerate them directly. However, if you divide the items into two halves and then enumerate them, this is feasible because each part has a maximum of 20 items. The weight and value of the selection method in the first half are recorded as W1 and V1, so that the largest selection method of V2 can be used when the total weight of W2 is less than or equal to w-W1.

Therefore, we need to think about how to efficiently find max {V2 | W2 ≤ W'} from the enumerated (W2, V2) set. First, we can exclude all J of W2 [I] ≤ W2 [J] and V2 [I]> = v2 [J. This can be done by sorting the W2 and V2 lexicographically. After that, all the remaining elements meet W2 [I] <W2 [J] <=> V2 [I] <V2 [J], to calculate max {V2 | W2 <= W'}, you only need to find the largest I that satisfies W2 [I] <= W. This can be done using a binary search. If the number of remaining elements is m, it takes O (logm) Time for a single search. Because m ≤ 2 ^ (n/2), the total time complexity of this algorithm is O (n * 2 ^ (n/2), which can solve the problem within the implementation.

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 50;const long long INF = 0x3fffffff;typedef long long LL;int n;LL w[N], v[N];LL W;pair <LL, LL> pi[1 << (N / 2)];void solve() { 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[j]; sv += v[j]; } } pi[i] = make_pair(sw, sv); } sort(pi, pi + (1 << n2)); int m = 1; for(int i = 1; i < (1 << n2); i++) { if(pi[m-1].second < pi[i].second) { pi[m++] = pi[i]; } } 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(pi, pi + m, make_pair(W - sw, INF)) - 1)->second; res = max(res, sv + tv); } } printf("%lld\n", res);}int main() { while(~scanf("%d%lld", &n, &W)) { for(int i = 0; i < n; i++) { scanf("%lld%lld", &w[i], &v[i]); } solve(); } return 0;}

Super large backpack problem (01 backpack)