zoj 3812 We Need Medicine

来源:互联网 发布:怎么成为淘宝文案兼职 编辑:程序博客网 时间:2024/06/05 19:59

题目链接

题意:有n~400中化学成分,每种成分要么选取重量Wi~50,获得Ti的TEV~200000值,要么不取,获得0的TEV值。之后又Q~400种病毒询问,对于每种病毒,要求配置质量为Mi~50的药物,并且TEV值为Si~200000,求出针对此病毒的化学成分组成,任意一组就行。

题解:每次询问固定M和TEV值,看是否能够组成,本来M和TEV要合并作为dp的维数,但是这样浪费了dp的值,发现M只有50,longlong状压后可以用一个数表示,那么只用dp【TEV】就行了,打印成分用一个from【TEV】【no】就行。

重点:400个物品,01背包。但是每次查询问(TEV,w)是否存在,利用w~50状压作为dp的值。

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)#define lowbit(x) ((x)&(-x))//能够取出数字二进制下的最后一个1表示成10进制。typedef long long ll;using namespace std;const int maxn = 2e5 + 100;const int key = (1<<51) - 1;int from[maxn][60], n, q, t[maxn], w[maxn];int tot = 200000;ll dp[maxn];map<ll, int> real;void getReal()//为了便于从ll转成编号。并且小心,只要跟状态有关的都用ll{    real.clear();    for(long long i = 0;i <= 50;i++)    {        ll tmp = (1ll<<i);        real[tmp] = i;    }}void getDp(){    CLR(dp);    CLR(from);//初始化为0    dp[0] = 1;//0的状态w是0    REP_D(i, 1, n)    {        for(int j = tot;j >= t[i];j--)        {            ll pre = dp[j];            ll now = (dp[j - t[i]]<<w[i]);            dp[j] = (pre|now);//搞出新的可以达到的情况            for(ll k = ((now^pre)&now);k != 0;k -= lowbit(k))//这个小心点写,要保证很小,取出新添的,然后lowbit一点一点。            {                ll tt = lowbit(k);                ll tmp = real[lowbit(k)];//记录                from[j][tmp] = i;            }        }    }}void solve(){    getReal();    getDp();    REP_D(i, 1, q)    {        int m, s;        scanf("%d%d", &m, &s);        ll sta = dp[s];        if((sta&(1ll<<m)))//注意ll,输出。        {            int now = from[s][m];            vector<int> ans;            while(now != 0)            {                ans.push_back(now);                s -= t[now];                m -= w[now];                now = from[s][m];            }            REP(j, 0, ans.size())            {                printf("%d%c", ans[j], (j == ans.size() - 1 ? '\n' : ' '));            }        }        else        {            printf("No solution!\n");        }    }}int main(){   // freopen("2Bin.txt", "r", stdin);    //freopen("3Bout.txt", "w", stdout);    int ncase;    scanf("%d", &ncase);    while(ncase--)    {        scanf("%d%d", &n, &q);        REP_D(i, 1, n)        {            scanf("%d%d", &w[i], &t[i]);        }        solve();    }    return 0;}


0 0
原创粉丝点击