• [HNOI2007]梦幻岛宝珠


    Description

    Luogu3188

    BZOJ1190

    Solution

    最naive的想法就是直接01背包,hash一下就可以得到10分的好成绩。

    考虑那个(a*2^b),我们可以先按(b)分组01背包,(f[i][j])表示只用(a*2^i)的东西,花费(j*2^i)的答案。

    然后合并各组物品,设(g[i][j])表示背包容量为(j*2^i)加上(w)在二进制下的后(i)位时的收益。最后答案就是(f[log_2mbox{highbit}(w)][1])。考虑转移,这个(j)有一部分是从(f[i])里贡献来的,另外的是从(g[i-1])里贡献的,所以:

    [g[i][j] = max(f[i][j-k]+g[i-1][k*2+w_i]) ]

    Code

    #include <algorithm>
    #include <bitset>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <queue>
    #include <set>
    #include <vector>
    
    namespace wyx {
    
    typedef long long ll;
    typedef double ld;
    
    ll read() {
        char c;
        ll ans = 0, fl = 1;
        for (c = getchar(); c > '9' || c < '0'; c = getchar())
            if (c == '-') fl = -1;
        ans = c - '0';
        for (c = getchar(); c >= '0' && c <= '9'; c = getchar())
            ans = ans * 10 + c - '0';
        return fl * ans;
    }
    
    const int N = 105;
    
    ll f[50][105], n, w, a[N], b[N], mx[N];
    ll hd[N], nxt[N];
    
    void pb(ll x, ll v) {
        nxt[x] = hd[v];
        hd[v] = x;
    }
    
    ll log2(ll x) {
        ll ans = -1;
        while (x) x >>= 1, ans++;
        return ans;
    }
    
    void main() {
        while (1) {
            n = read(), w = read();
            if (n == -1 && w == -1) break;
            memset(f, 0, sizeof f);
            memset(hd, 0, sizeof hd);
            memset(b, 0, sizeof b);
            memset(a, 0, sizeof a);
            memset(nxt, 0, sizeof nxt);
            memset(mx, 0, sizeof mx);
            for (int i = 1; i <= n; ++i) {
                b[i] = read();
                a[i] = read();
                int p = 0;
                while (!(b[i] & 1)) {
                    b[i] >>= 1;
                    p++;
                }
                pb(i, p);
                mx[p] += b[i];
            }
            for (int i = 0; i <= 30; ++i) {
                for (int j = hd[i]; j; j = nxt[j]) {
                    for (int k = mx[i]; k; --k) {
                        if (k - b[j] >= 0)
                            f[i][k] = std::max(f[i][k], f[i][k - b[j]] + a[j]);
                    }
                }
            }
            for (int i = 1; i <= 30; ++i) {
                mx[i] += (mx[i - 1] + 1) / 2;
                for (int j = mx[i]; j >= 0; --j) {
                    for (int k = 0; k <= j; ++k) {
                        f[i][j] = std::max(
                            f[i][j],
                            f[i][j - k] +
                                f[i - 1][std::min(mx[i - 1],
                                                  (k << 1) | (w >> (i - 1) & 1))]);
                    }
                }
            }
            int len = 0;
            while (w >> len) len++;
            len--;
            printf("%lld
    ", f[len][1]);
        }
    }
    
    }  // namespace wyx
    
    int main() {
        wyx::main();
        return 0;
    }
    
  • 相关阅读:
    vmware esxi 过期,激活
    mysql 导入csv文件
    定时登录下载sftp服务器上的某些有规则的文件
    修改tmp的临时目录的地址
    jetty权威指南
    将linux下的rm命令改造成mv到指定的目录下
    mysql 5.6 grant授权的时候出现问题
    Keras vs. PyTorch
    Visualizing LSTM Layer with t-sne in Neural Networks
    keras Lambda 层
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/hnoi2007mhdbz.html
Copyright © 2020-2023  润新知