[HNOI2007]梦幻岛宝珠

· · 题解

时间复杂度 O(T \ast len \ast 1000 \ast 1000) , 常数略大。

加O2才过的垃圾代码:

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 2010;

int n, m;
long long w;
long long ai[MAXN], bi[MAXN], val[MAXN], f[32][1010];

int main(){
    while(cin >> n >> w){
        if (n == -1 && w == -1) break;
        memset(f, 0, sizeof(f));
        for(int i = 1; i <= n; i++){
            long long c;
            cin >> c >> val[i];
            ai[i] = (c / (c & (-c)));
            bi[i] = 0;
            for(c = (c & (-c)) >> 1; c; c >>= 1) bi[i]++;
        }

        for(int i = 1; i <= n; i++)
            for(int a = 1000; a >= ai[i]; a--)
                f[bi[i]][a] = max(f[bi[i]][a], f[bi[i]][a - ai[i]] + val[i]);   

        int len = 0;
        for(long long s = w>>1; s; s >>= 1) len++;

        long long  ans = 0;
        for(int b = 1; b <= len; b++){
            for(int a = 1000; a >= 0; a--)
                for(int k = 0; k <= a; k++){
                    f[b][a] = max(f[b][a], f[b][a - k] + f[b - 1][min(1000, (k << 1) | ( (w & (1 << (b - 1))) != 0))]);
                }
        }

        cout << f[len][1] << endl;

    }

    return 0;
}