zoukankan      html  css  js  c++  java
  • HDU 3247 Resource Archiver[AC自动机+最短路+dp]

    http://acm.hdu.edu.cn/showproblem.php?pid=3247
    题意:给n个源代码串,m个病毒串(都是01串),求最短的串,包含所有源代码串,但不包含任何病毒串,输出这个最短串的长度。
    (题目没说如果不存在该输出什么,那应该就是保证一定存在吧。即没有任何一个病毒串是源代码串的子串)

    思路:将所有串都加入自动机中,预处理出所有代码串之间的最短路(不经过病毒串的最短路),然后问题就变成了从trie树根节点开始,经过每个代码串结点各一次的最短路径,类似于TSP,用状压dp可解。

    #include<cassert>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<set>
    #include<queue>
    #include<map>
    using namespace std;
    #define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
    #define dep(i,f,t) for(int i = (f), _end = (t); i >= _end; --i)
    #define clr(c,x) memset(c,x,sizeof(c));
    #define debug(x) cout<<"debug  "<<x<<endl;
    const int INF = 0x3f3f3f3f;
    
    inline int RD(){ int res; scanf("%d",&res); return res; }
    
    #define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas)
    
    //***************************************************************
    
    const int maxs = 60006;
    int dis[11][11];
    int dp[1025][11];
    
    struct Trie{
        int next[maxs][2];
        int end[maxs];
        int fail[maxs];
        int sz;
        void init(){
            sz = fail[0] = end[0] = 0;
            clr(next[0], 0);
        }
        int newnode(){
            ++sz;
            fail[sz] = end[sz] = 0;
            clr(next[sz], 0);
            return sz;
        }
        int insert(char *s, int id){
            int u = 0;
            while(*s){
                int nid = *s++ - '0';
                int &v = next[u][nid];
                if(!v) v = newnode();
                u = v;
                if(end[u] < 0)return 0;
            }
            if(id > 0){
                if(next[u][0] || next[u][1] || end[u])return -1;
            }else{
                next[u][0] = next[u][1] = 0;
            }
            end[u] = id;
            return u;
        }
        void build(){
            queue<int> q;
            rep(c,0,1) if(next[0][c])q.push(next[0][c]);
            while(!q.empty()){
                int u = q.front();
                q.pop();
                int fu = fail[u];
                if(end[fu] == -1){
                    end[u] = -1;
                }
                rep(c,0,1){
                    int &v = next[u][c];
                    if(v){
                        q.push(v);
                        fail[v] = next[fu][c];
                    }else{
                        v = next[fu][c];
                    }
                }
            }
        }
    
        int dt[maxs];
        void bfs(int s){
            clr(dt, -1);
            queue<int> q;
            dt[s] = 0;
            q.push(s);
            while(!q.empty()){
                int u = q.front(); 
                q.pop();
    
                if(u == 0 || end[u] > 0) dis[end[s]][end[u]] = dt[u];
    
                rep(c,0,1){
                    int v = next[u][c];
                    if(end[v] < 0 || dt[v] >= 0)continue;
                    dt[v] = dt[u] + 1;
                    q.push(v);
                }
            }
        }
    
        int solve(int n){
            clr(dp, INF);
            rep(i,1,n){
                dp[1<<(i-1)][i] = dis[0][i];
            }
            rep(S,1,(1<<n)-2){
                rep(i,1,n)if(S>>(i-1)&1){
                    if(dp[S][i] == INF)while(1)puts("**");
                    rep(j,1,n)if( !(S>>(j-1)&1) ){
                        int &nxt = dp[S|(1<<(j-1))][j]; 
                        nxt = min(nxt, dp[S][i] + dis[i][j]);
                    }
                }
            }
            return *min_element(dp[(1<<n)-1]+1, dp[(1<<n)-1]+n+1);
        }
    }ac;
    
    char tmp[50005];
    int mp[11];
    int main(){
        int n,m;
        while(scanf("%d%d",&n,&m), n){
            ac.init();
            clr(dis, INF);
            for(int i = 1; i <= n; ){
                scanf("%s",tmp);
                int t = ac.insert(tmp, i);
                if(t > 0){
                    dis[0][i] = strlen(tmp);
                    mp[i] = t;
                    ++i;
                }else{
                    --n;
                }
            }
            rep(i,1,m){
                scanf("%s",tmp);
                ac.insert(tmp, -1);
            }
            ac.build();
            rep(i,1,n){
                ac.bfs(mp[i]);
            }
            int ans = ac.solve(n);
            printf("%d
    ",ans);
        }
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    vue mock数据设置
    vue 的全局拦截器
    vue-resource基础介绍
    快速排序
    Node 中的 stream (流)
    v8垃圾回收和js垃圾回收机制
    Node内存限制与垃圾回收
    ReactNative http网络通讯
    luogu1829 [国家集训队]Crash的数字表格
    luogu2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861969.html
Copyright © 2011-2022 走看看