HDU 3247 Resource Archiver(AC自动机+BFS+状态DP)
来源:互联网 发布:福州爆米花网络 编辑:程序博客网 时间:2024/06/06 00:40
转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:给出n个资源,m个病毒,将资源串拼接成一个串,必须包含所有的资源串,可以重叠,但是不能包含病毒
问最小的长度为多少
http://acm.hdu.edu.cn/showproblem.php?pid=3247
不会做,看题解啊看题解,看了也不会。。。。
将所有的资源串和病毒串都放在Trie树里建立起来,当然作上相应的标记。然后建立fail指针之后
从资源串的结尾出发,BFS,记录能到达其它资源串结尾的步数。得到所有资源串结尾状态的距离邻接阵。
之后是状态压缩DP
dp[i][j]表示资源串的状态为i时,当前处在Trie上的状态j,最短长度。
感觉静态的写得怪怪的,而且不直观。。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define eps 1e-10#define N 100005#define inf 1<<20#define zero(a) (fabs(a)<eps)#define lson (step<<1)#define rson (step<<1|1)using namespace std;struct Trie{ int next[2],fail; int virus,source; void Init(){next[0]=next[1]=0;fail=source=virus=0;}}tree[N];int n,m;int tot,cnt;int path[205][205];int pos[205];int dp[1<<10][205];//dp[i][j]表示状态为i时,以j结尾的最少步数char str[50005];void Insert(char *s,int len,int kind){ int p=0; for(int i=0;i<len;i++){ if(tree[p].next[s[i]-'0']==0){ tree[++tot].Init(); tree[p].next[s[i]-'0']=tot; } p=tree[p].next[s[i]-'0']; } if(kind>=0) tree[p].source=1<<kind; else tree[p].virus=1;}void Bulid_fail(){ int que[N]; int head=0,tail=0; que[tail++]=0; while(head<tail){ int p=que[head++]; for(int i=0;i<2;i++){ if(tree[p].next[i]==0) tree[p].next[i]=tree[tree[p].fail].next[i]; else{ int q=tree[p].next[i]; if(p) tree[q].fail=tree[tree[p].fail].next[i]; tree[q].source|=tree[tree[q].fail].source; tree[q].virus|=tree[tree[q].fail].virus; que[tail++]=q; } } }}void Bfs(int u){ int que[N]; int head=0,tail=0; int dist[N]; memset(dist,-1,sizeof(dist)); que[tail++]=pos[u]; dist[pos[u]]=0; while(head<tail){ int p=que[head++]; for(int i=0;i<2;i++){ int q=tree[p].next[i]; if(dist[q]<0&&!tree[q].virus){ dist[q]=dist[p]+1; que[tail++]=q; } } } for(int i=0;i<cnt;i++) path[u][i]=dist[pos[i]];}int DP(){ memset(dp,-1,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]<0) continue; for(int k=0;k<cnt;k++){ if(path[j][k]<0) continue; if(dp[i|tree[pos[k]].source][k]==-1) dp[i|tree[pos[k]].source][k]=dp[i][j]+path[j][k]; else dp[i|tree[pos[k]].source][k]=min(dp[i|tree[pos[k]].source][k],dp[i][j]+path[j][k]); } } } int ans=inf; for(int i=0;i<cnt;i++) if(dp[(1<<n)-1][i]!=-1) ans=min(ans,dp[(1<<n)-1][i]); return ans==inf?-1:ans;}int main(){ // freopen("1.in","r",stdin); while(scanf("%d%d",&n,&m)!=EOF&&n+m){ tree[0].Init();cnt=1;tot=0; for(int i=0;i<n;i++){ scanf("%s",str); Insert(str,strlen(str),i); } for(int i=0;i<m;i++){ scanf("%s",str); Insert(str,strlen(str),-1); } Bulid_fail(); for(int i=1;i<=tot;i++) if(tree[i].source) pos[cnt++]=i; for(int i=0;i<cnt;i++) Bfs(i); printf("%d\n",DP()); } return 0;}
- HDU 3247 Resource Archiver(AC自动机+BFS+状态DP)
- HDU 3247 Resource Archiver(AC自动机+BFS+状态DP)
- hdu 3247 Resource Archiver(AC自动机+BFS+DP)
- hdu 3247 Resource Archiver (ac自动机+BFS+状压dp)
- HDU 3247-Resource Archiver(AC自动机+BFS+DP)
- HDU 3247 Resource Archiver (AC自动机 + BFS + 状态压缩DP)
- HDU 3247 Resource Archiver AC自动机 + BFS最短路 + 状压DP
- hdu 3247 Resource Archiver(AC自动机+状压DP)
- [AC自动机+spfa+状压dp] hdu 3247 Resource Archiver
- HDU 3247 Resource Archiver[AC自动机+最短路+dp]
- 【ZOJ】 3190 Resource Archiver AC自动机+BFS预处理+DP
- hdu3247 Resource Archiver AC自动机+状态压缩DP
- HDU3247 Resource Archiver(AC自动机+DP)
- hdu3341 Resource Archiver AC自动机+DP
- HDU 3247 ac自动机+bfs+状态压缩dp
- 【AC自动机】 HDOJ 3247 Resource Archiver
- HDOJ-3427 & ZOJ-3190 Resource Archiver AC自动机压缩状态DP..
- HDU 3247 AC自动机 + 状态压缩dp
- 关于java io学习
- PC上安装Mac
- VS2010下如何为Combo Box 添加多行数据
- javaScript常用的正则表达式
- 浅谈C++多态性
- HDU 3247 Resource Archiver(AC自动机+BFS+状态DP)
- Codeforces 1A - Theater Square
- C++对象的复制
- android 瀑布流
- 一个小制作
- linux安装mysql提示mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
- ZOJ-3641-Information Sharing
- String与Date互转
- JAVA项目打包生成.exe文件