zoj 3812 We Need Medicine(01背包)

题目链接:zoj 3812 We Need Medicine

题目大意:有n中化学成分,每种成分要么选取重量Wi,获得Ti的TEV值,要么不取,获得0的TEV值。现在对于每种病

毒,要求配置质量为Mi的药物,并且TEV值为Si,求化学成分组成。

解题思路:看了别人的题解,以前居然不知道背包转移可以用二进制。

因为质量总共才50,所以用一个long long的二进制数表示说哪些质量是可祖长的,这样的话只要开一个20W的数组

s,s[i]表示说TEV值为i时质量可以为多少。然后每次在用lowbit处理出新增的可能,用dp[i][j]记录路径。

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>

using namespace std;

#define lowbit(x) ((x)&(-x))

typedef unsigned long long ull;
typedef long long ll;
const int maxn = 405;
const int maxt = 200000;

int N, Q, W[maxn], T[maxn];
short dp[maxt + 5][52];
map<ll, int> G;
ull s[maxt];

void init () {
    scanf("%d%d", &N, &Q);
    for (int i = 1; i <= N; i++)
        scanf("%d%d", &W[i], &T[i]);

    ull bit = (1LL<<51) - 1;
    memset(s, 0, sizeof(s));
    memset(dp, 0, sizeof(dp));
    s[0] = 1;

    for (int i = 1; i <= N; i++) {
        for (int j = maxt; j >= T[i]; j--) {
            ull v = s[j];

            s[j] |= ((s[j-T[i]]<<W[i]) & bit);

            for (ll k = s[j]^v; k != 0; k -= lowbit(k))
                dp[j][G[lowbit(k)]] = i;
        }
    }
}

int main () {

    for (int i = 0; i <= 50; i++)
        G[1LL<<i] = i;

    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init();

        int x, y;
        while (Q--) {
            scanf("%d%d", &x, &y);

            if (dp[y][x]) {
                int u = dp[y][x];
                printf("%d", u);
                while (u) {
                    y -= T[u];
                    x -= W[u];
                    u = dp[y][x];

                    if (u)
                        printf(" %d", u);
                }
                printf("\n");
            } else
                printf("No solution!\n");
        }
    }
    return 0;
}
时间: 2024-08-15 17:03:44

zoj 3812 We Need Medicine(01背包)的相关文章

ZOJ 3812 We Need Medicine 01背包+位优化

题目链接:点击打开链接 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <map> typedef unsigned long long ll; using namespace std; const int N = 400 + 1; const int M = 200000 + 1; int t[N], w[N], g[5

ZOJ 3812 We Need Medicine(牡丹江网络赛D题)

ZOJ 3812 We Need Medicine 题目链接 思路:dp[i][j][k]表示第i个物品,组成两个值为j和k的状态,这样会爆掉,所以状态需要转化一下 首先利用滚动数组,可以省去i这维,然后由于j最大记录到50,所以可以把状态表示成一个二进制数s,转化成dp[k] = s,表示组成k状态能组成s,这样空间复杂度就可以接受了,然后这题时限还可以,就这样去转移,然后记录下路径即可 代码: #include <cstdio> #include <cstring> #incl

ZOJ 3812 We Need Medicine

题意: 一个物品重w效力t  给出所有n个物品  有q个询问  每个询问输出w的和为m同时t的和为s的方案 思路: 明显就是01背包  只不过一个东西在两个维度上有价值  由于w只有50因此可以状压 先想如何输出方案  利用f[i][j]表示sumw=i同时sumt=j时候装进包里的最后一个物品  那么输出这个物品后i和j都减去这个物品的w和t  就可以到达新的状态  这样可以一直到背包为空  最多循环50次 最难得是dp过程  之前提到状压  这题精髓就是状压后50位状态一起转移  用g[i]

ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)

参考:http://blog.csdn.net/qian99/article/details/39138329 参考的链接里说明得很好,注释也很好...thanks for sharing 朴素的想法不难,dp[i][j][k]类似背包做法即可. 但朴素思想复杂度过高. 这里主要是用到 dif 那个变量,只枚举新增的集合. #include <cstdio> #include <cstring> #include <iostream> #include <algo

zoj 3812 We Need Medicine (dp 位优化 巧妙记录路径)

We Need Medicine Time Limit: 10 Seconds      Memory Limit: 65536 KB      Special Judge A terrible disease broke out! The disease was caused by a new type of virus, which will lead to lethal lymphoedema symptom. For convenience, it was namedLL virus.

zoj 3812 We Need Medicine (dp 状压)

先贴一下转载的思路和代码,,,:http://blog.csdn.net/qian99/article/details/39138329 状压dp博大精深啊,以后看到n<=50都可以往状压上想,orz We Need Medicine Time Limit: 10 Seconds                                     Memory Limit: 65536 KB                                                   

ZOJ 3211 Dream City DP 01背包 经典问题

题目大意:JAVAMAN 到梦幻城市旅游见到了黄金树,黄金树上每天回结出金子.已经有n棵树,JAVAMAN要停留m天,每天只能砍掉一棵树,砍掉树后就能得到树上的黄金.给定n棵树上原有的黄金a[i]和每天可以新增加的黄金b[i],求他最多可以得到多少黄金.中途如果有1天不砍树的话,之后的日子久不能砍树,所有最好每天都砍树,或者直到树被砍完. 这个其实是个背包问题,把日期看成背包的容量.然后n棵树当成n个物品. 假设我们取得由某 m 棵树组成的最优解.如果先砍的树的b值比后砍的树的b值大, 那么我们

bnu 28890 &amp;zoj 3689——Digging——————【要求物品次序的01背包】

Digging Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ID: 368964-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory 2-SAT Articulation

zoj 2822 Sum of Different Primes (01背包)

///给你n 求他能分解成多少个的不同的k个素数相加之和 ///01背包,素数打表 # include <stdio.h> # include <algorithm> # include <string.h> # include <math.h> # include <iostream> using namespace std; int cot; int used[1500]; int prime[1500]; void sushu()///素数