HDU 3247 Resource Archiver(AC自动机+BFS+状态DP)

来源:互联网 发布:淘宝店太坑了 编辑:程序博客网 时间:2024/06/04 17:42

题目:给出n个资源,m个病毒,将资源串拼接成一个串,必须包含所有的资源串,可以重叠,但是不能包含病毒

问最小的长度为多少


将所有的资源串和病毒串都放在Trie树里建立起来,当然作上相应的标记。然后建立fail指针之后

从资源串的结尾出发,BFS,记录能到达其它资源串结尾的步数。得到所有资源串结尾状态的距离邻接阵。

之后是状态压缩DP

dp[i][j]表示资源串的状态为i时,最后一个已取资源串是j时,最短长度。

#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-9#define maxn 60010#define MOD 1000000007int n,m;int dp[1050][13];int path[13][13];int pos[13];struct Trie{    int next[maxn][2],fail[maxn],en[maxn];    int root,L,cnt;    void init()    {        L = 0;        pos[0] = 0;        root = newnode();    }    int newnode()    {        for(int i = 0; i <= 1; i++)            next[L][i] = -1;        en[L++] = 0;        return L-1;    }    void Insert(char a[],int flag)    {        int now = root;        int len = strlen(a);        for(int i = 0; i < len; i++)        {            int x;            if(a[i] == '0')                x = 0;            else                x = 1;            if(next[now][x] == -1)                next[now][x] = newnode();            now = next[now][x];        }        en[now] = flag;    }    void build()    {        queue<int> Q;        fail[root] = root;        for(int i = 0; i <= 1; i++)        {            if(next[root][i] == -1)                next[root][i] = root;            else            {                fail[next[root][i]] = root;                Q.push(next[root][i]);            }        }        while(!Q.empty())        {            int now = Q.front();            Q.pop();            if(en[fail[now]] == -1)                en[now] = en[fail[now]];            else                en[now] |= en[fail[now]];            for(int i = 0; i <= 1; i++)            {                if(next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else                {                    fail[next[now][i]] = next[fail[now]][i];                    Q.push(next[now][i]);                }            }        }    }    void bfs(int u,int cnt)    {        queue<int> q;        q.push(pos[u]);        int dis[maxn];        memset(dis,-1,sizeof(dis));        dis[pos[u]] = 0;        while(!q.empty())        {            int v = q.front();            q.pop();            for(int i = 0; i < 2; i++)            {                int k = next[v][i];                if(dis[k] < 0 && en[k] != -1)                {                    dis[k] = dis[v] + 1;                    q.push(k);                }            }        }        for(int i = 0; i < cnt; i++)            path[u][i] = dis[pos[i]];    }    void solve()    {        int cnt = 1;        for(int i = 0; i < L; i++)            if(en[i] > 0)                pos[cnt++] = i;        for(int i = 0; i < cnt; i++)            bfs(i,cnt);//            for(int i = 0; i <= n; i++)//            {for(int j = 0; j <= n; j++)//                printf("%d ",path[i][j]);printf("\n");}        memset(dp,INF,sizeof(dp));        dp[0][0] = 0;        for(int i = 0; i < (1<<n); i++)            for(int j = 0; j < cnt; j++)                if(dp[i][j] < INF)                {                    for(int k = 0; k < cnt; k++)                    {                        if(path[j][k] < 0 || j == k)                            continue;                        dp[i|en[pos[k]]][k] = min(dp[i|en[pos[k]]][k],dp[i][j]+path[j][k]);                    }                }        int ans = INF;        for(int i = 0; i < cnt; i++)            ans = min(ans,dp[(1<<n)-1][i]);        printf("%d\n",ans);    }} ac;int main(){    int t,C = 1;    //scanf("%d",&t);    while(scanf("%d%d",&n,&m) && (n+m))    {        ac.init();        char s[1010];        for(int i = 0; i < n; i++)        {            scanf("%s",s);            ac.Insert(s,1<<i);        }        for(int i = 0; i < m; i++)        {            scanf("%s",s);            ac.Insert(s,-1);        }        ac.build();        ac.solve();    }    return 0;}


0 0
原创粉丝点击