2014 牡丹江网络赛部分题解(ZOJ 3809 - 3818)

提交地址 (ZOJ 3809 - 3818)

参考别人代码地址

B   构造


D   We Need Medicine

DP + 状态压缩      注意到M范围只有50,可以状压

valid[i] - S为i时,能够组成的M集合。first[i][j]记录路径。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#include<cmath>
#include<vector>
typedef long long ll;
#define prt(k) cout<< #k" = " << k<< "   \n";   ///
typedef unsigned long long ull;
const int N = 402;
const int M = 200000;
const int MM = 50;

ull valid[M+20];
int aa[N], bb[N];
int first[M+10][MM+1];

int main()
{
    int re; scanf("%d", &re);
    while(re--)
    {
        int n, q;
        scanf("%d%d", &n, &q);
        memset(valid, 0, sizeof valid);
        memset(first, -1, sizeof first);
        valid[0] = 1;
        for(int i = 0; i < n; i++)
        {
            int a, b;
            cin>>b>>a;
            aa[i]= a; bb[i] = b;
            for(int j = M; j >= a; j--)
            {
                ull tmp = valid[j];
                valid[j] |= ((valid[j - a] << b) & ((1ull << MM + 1) - 1)) ;
                for(ull bit = tmp ^ valid[j]; bit; bit = bit - 1 & bit)
                {
                    first[j][__builtin_ctzll(bit)] = i;   /// bit = 1<<n
                }
            }
        }
        while( q-- )
        {
            int b, a;
            cin>> b>> a;
            if(valid[a]>>b & 1)
            {
                bool isfirst = true;
                while(a && b)
                {
                    int i = first[a][b];
                    if(isfirst) isfirst = 0;
                    else putchar(' ');
                    cout<<i+1;
                    a -= aa[i];
                    b -= bb[i];
                }
                cout<<endl;
            }
            else cout<<"No solution!\n";
        }
    }
}


E   树状数组


F   DFS


I   字符串哈希


你可能感兴趣的:(2014 牡丹江网络赛部分题解(ZOJ 3809 - 3818))