E - Neverland Sarah HYSBZ - 1190 01 backpack is difficult to deform

E - Sarah Neverland

 HYSBZ - 1190 

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;
}
View Code

 

Guess you like

Origin www.cnblogs.com/EchoZQN/p/11534462.html