zoukankan      html  css  js  c++  java
  • SPOJ AMR11C Robbing Gringotts [搜索+二分匹配] 康某

    题意:有N个贼,M个地窖(N,M<=50)

    每个贼有个背包,容量为A1,A2.....AN

    每个地窖里有X(X <= 25)件东西,每件东西的价值为B1,B2.。。。BX(<=10000000)

    贼都很贪,只会去偷能把自己背包装满的地窖,求最多能偷到多少东西

    这个问题要分成两个阶段考虑……

    一是谁能偷哪个地窖,问题转化成了01背包问题……由于数据太大,咱们只能搜……

    然后,就是匹配问题,KM可以,另外,按照賊的背包容量从大到小顺序匈牙利也行……

    于是,对每个地窖,一个Naive的实现:

    void dfs(int lv,int num,int deep) {
        if (num > X[N - 1]) return;
        if (lv == deep) {
            visit[num] = mark;
            return;
        }
        dfs(lv + 1, num + A[lv], deep);
        dfs(lv + 1, num, deep);
    }

    复杂度 2^25,产生了这个地窖所有能拼出来的可能数

    然后还得枚举,复杂度 50 * 50 << 25 …… 似乎进入了TLE的节奏……

    看了解题报告才明白,Meet-in-middle……也就是DFS一半,哈希起来……然后另一边进去查找……

    经过优化,复杂度变成 50 * Max(1 << 15,50 << 10)……

    P.S:如果去阿三赛区会不会有拿金进Final的希望……昨天单挑都做了6道,按榜看来已然前12……

    第7道差这么个Meet in middle优化……7道前三……

    完整代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int N,M;
    int adj[55][55];
    int A[55];
    int X[55];
    int visit[10000001];
    int deep;
    int mark = 1;
    
    int match[55];
    bool vv[55];
    
    void dfs(int lv,int num,int deep) {
        if (num > X[N - 1]) return;
        if (lv == deep) {
            visit[num] = mark;
            return;
        }
        dfs(lv + 1, num + A[lv], deep);
        dfs(lv + 1, num, deep);
    }
    
    void dfs_2(int lv,int num,int deep,int fa) {
        if (num > X[N - 1]) return;
        if (lv == deep) {
            for (int j = 0; j < N; j++) {
                if (X[j] - num >= 0 && visit[X[j] - num] == mark) {
                    adj[j][fa] = X[j];
                }
            }
            return;
        }
        dfs_2(lv + 1, num + A[lv], deep, fa);
        dfs_2(lv + 1, num, deep, fa);
    }
    
    bool dfs(int k) {
        if (vv[k]) return false;
        vv[k] = true;
        for (int i = 0; i < M; i++) {
            if (adj[k][i]) {
                int tt = match[i];
                match[i] = k;
                if (tt == -1 || dfs(tt)) return true;
                match[i]=tt;
            }
        }
        return false;
    }
    
    int main() {
        int nn; scanf("%d",&nn);
        while (nn--) {
            scanf("%d%d",&N,&M);
            memset(adj,0,sizeof(adj));
            memset(A,0,sizeof(A));
            for (int i = 0; i < N; i++) scanf("%d",X + i);
            sort(X,X + N);
            for (int i = 0; i < M; i++) {
                scanf("%d",&deep);
                for (int j = 0; j < deep; j++) scanf("%d",A + j);
                mark ++;
                if (deep < 15) {
                    dfs(0,0,deep);
                    for (int j = 0; j < N; j++) {
                        if (visit[X[j]] == mark) {
                            adj[j][i] = X[j];
                        }
                    }
                } else {
                    dfs(0,0,15);
                    dfs_2(15,0,deep,i);
                }
                for (int j = 0; j < N; j++) {
                    if (visit[X[j]] == mark) {
                        adj[j][i] = true;
                    }
                }
            }
            memset(match,0xff,sizeof(match));
            int ans = 0;
            for (int i = N - 1; i >= 0; i--) {
                memset(vv,0,sizeof(vv));
                if (dfs(i)) ans += X[i];
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    C语言修炼-第2天
    static_cast, dynamic_cast, reinterpret_cast, const_cast的区别
    构造函数不能为虚函数的原因
    matlab2016b ubuntu命令行安装 + matconvnet的安装
    python debug open_files
    构造函数不能被继承的原因
    NNVM代码阅读
    ncnn阅读
    Deep TEN: Texture Encoding Network
    git命令笔记
  • 原文地址:https://www.cnblogs.com/sweetsc/p/2582858.html
Copyright © 2011-2022 走看看