HDU 3247 Resource Archiver[AC自动机+最短路+dp]
2015-05-07 23:31
417 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3247
题意:给n个源代码串,m个病毒串(都是01串),求最短的串,包含所有源代码串,但不包含任何病毒串,输出这个最短串的长度。
(题目没说如果不存在该输出什么,那应该就是保证一定存在吧。即没有任何一个病毒串是源代码串的子串)
思路:将所有串都加入自动机中,预处理出所有代码串之间的最短路(不经过病毒串的最短路),然后问题就变成了从trie树根节点开始,经过每个代码串结点各一次的最短路径,类似于TSP,用状压dp可解。
题意:给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 4000 [(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\n",ans); } return 0; }
相关文章推荐
- HDU 3247 Resource Archiver[AC自动机+最短路+dp]
- HDU 3247 Resource Archiver AC自动机 + BFS最短路 + 状压DP
- HDU 3247 Resource Archiver(AC自动机+状态压缩dp+最短路BFS)
- hdu 3247(ac自动机+状态压缩dp+最短路)
- HDU 3247 Resource Archiver (AC自动机 + BFS + 状态压缩DP)
- HDU 3247 AC自动机 + 状态压缩dp
- hdu 2833 WuKong(最短路 + dp)
- HDU 4856 Tunnels (最短路+状压DP)
- HDU 4511 (AC自动机 DP)
- hdu 1676 Full Tank? 限制最短路 dp 蛮有技巧的~
- HDU-4518 吉哥系列故事——最终数 AC自动机+数位DP
- HDU 3339 In Action(最短路+DP)
- HDU - 1142 A Walk Through the Forest (DP + 最短路)
- HDU沈阳网络赛:transaction transaction transaction(树形dp & 最短路)
- HDU 2243 AC自动机->DP->附矩阵乘法板子
- HDU - 3339 In Action(最短路+dp)
- HDU 3247 Resource Archiver(自动机+状态压缩DP)
- HDU 1625 Censored! (AC自动机 + 大数 + dp)
- hdu 4276 The Ghost Blows Light(树形DP+最短路+分组背包)好题。。。
- HDU 4568 Hunter 最短路+状压DP