E - Sarah Neverland
The topic I find it hard to see the problem solution have watched for a long time.
First get a rough idea is grouped, each number can be divided into a * 2 ^ b so the same numbers are divided into a group b.
01 backpack carried out within each group, this operation is relatively simple.
More difficult is transferred between the groups.
Defined dp [i] [j] denotes the maximum value of the i-layer capacity of j * 2 ^ i.
So how transfer from i 1-layer to layer i do?
Because the dp [i] [j] to the i-layer capacity is the capacity of the i-th layer itself so that the total capacity before + j * 2 ^ i + w & ((1 << i) -1)
Suppose only the i-th layer (jk) * 2 ^ i so much capacity, then the first (i-1) Multi-layer may also be k * 2 ^ i so much capacity.
How transfer that like this it?
Suppose from dp [i-1] [x] that is transferred from the layer i-1 x * 2 ^ (i-1) the capacity of the
Since the i-layer in the end a total of j * 2 ^ i + w & ((1 << i) -1) the capacity of the i-th layer (jk) * 2 ^ i capacity
所以 x*2^(i-1)=j*2^i+w&((1<<i)-1)-(j-k)*2^i
解出 x=2*k+(w>>(i-1)&1)
Therefore, the transfer equation dp [i] [j] = max (dp [i] [j], dp [i-1] [2 * k + (w >> (i-1) & 1)])
Because a total of only n gem, if these n stones placed in the same group, and a * 2 ^ b are of a maximum of 10 this second dimension is only 10 * n
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> #include <iostream> #define inf 0x3f3f3f3f using namespace std; const int maxn = 1000 + 10; typedef long long ll; int dp[35][1010]; int main() { int n, m; while (scanf("%d%d", &n, &m) && n != -1 && m != -1) { memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) { int w, val, a = 0; scanf("%d%d", &w, &val); while (w % 2 == 0) w /= 2, a++; for (int j = 1000; j >= w; j--) dp[a][j] = max(dp[a][j], dp[a][j - w] + val); } int w = m, up = 0; for (int i = w; i; i >>= 1) up++; up--; for (int i = 1; i <= up; i++) { for (int j = 1000; j >= 0; j--) { for (int k = 0; k <= j; k++) { dp[i][j] = max(dp[i][j], dp[i][j - k] + dp[i - 1][min(1000, 2 * k + ((w >> (i - 1)) & 1))]); } } } printf("%d\n", dp[up][1]); } return 0; }