链接

这题没想到怎么做,问了下p队长,大悟。。

先求出任意两串的在trie树上的最短距离,期间是不能走到不合法的地方,我是用spfa求得,在更新和加入节点时判断一下是不是合法位置。

求出最短距离之后,找出一条从0出发遍历所有串的最短距离,可以dp出,dp[i][j]表示当前状态以节点j串结尾的最短距离。

枚举一下最后结尾的为哪一个串时距离最短。

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 60010
#define M 10010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
const int child_num = ;
int w[][];
bool vis[N];
int dis[N];
class AC
{
private:
int ch[N][child_num];
int fail[N];
int Q[N];
int val[N],vv[N];
int id[];
int sz ;
int po[];
int dp[][];
public:
void init()
{
fail[] = ;
id[''] = ;
id[''] = ;
}
void reset()
{
memset(ch[],,sizeof(ch[]));
memset(val,,sizeof(val));
memset(vv,,sizeof(vv));
sz=;
}
void insert(char *a ,int key)
{
int p = ;
for( ; *a ; a++)
{
int d = id[*a];
if(ch[p][d]==)
{
memset(ch[sz],,sizeof(ch[sz]));
ch[p][d] = sz++;
}
p = ch[p][d];
}
if(key!=-)
{
val[p] = <<(key-);
po[key] = p;
}
else
{
vv[p] = ;
}
}
void construct()
{
int i,head=,tail = ;
for(i = ; i < child_num ; i++)
if(ch[][i])
{
fail[ch[][i]] = ;
Q[tail++] = ch[][i];
}
while(head!=tail)
{
int u = Q[head++];
vv[u]|=vv[fail[u]];
val[u]|=val[fail[u]];
for(i = ;i < child_num ; i++)
{
if(ch[u][i])
{
fail[ch[u][i]] = ch[fail[u]][i];
Q[tail++] = ch[u][i];
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
int spfa(int st,int ed)
{
int i;
memset(vis,,sizeof(vis));
for(i = ; i <= sz ;i++)
dis[i] = INF;
dis[st] = ;
vis[st] = ;
queue<int>q;
q.push(st);
while(!q.empty())
{
int u = q.front();
q.pop();
for(i = ; i < child_num; i++)
{
int v = ch[u][i];
if(vv[v]) continue;
dis[v] = min(dis[v],dis[u]+);
//if(st == 4&&ed==8)
//cout<<v<<" "<<dis[v]<<" "<<u<<endl;
if(!vis[v])
{
vis[v] = ;
q.push(v);
}
}
}
return dis[ed];
}
void find_dis(int n)
{
int i,j;
po[] = ;
for(i = ; i <= n ;i++)
{
w[][i] = w[i][] = spfa(,po[i]);
//cout<<w[0][i]<<endl;
}
for(i = ; i <= n; i++)
for(j = ; j <= n ;j++)
{
w[i][j] = spfa(po[i],po[j]);
// cout<<w[i][j]<<" "<<i<<" "<<j<<endl;
}
}
void work(int n)
{
int i,j,g;
for(i = ; i < (<<n) ; i++)
for(j = ;j <= n; j++)
dp[i][j] = INF;
dp[][] = ;
for(i = ;i < (<<n) ; i++)
{
for(j = ;j <= n ;j++)
{
for(g = ; g <= n ;g++)
{
if((<<(g-))&i) continue;
dp[i+(<<(g-))][g] = min(dp[i+(<<(g-))][g],dp[i][j]+w[j][g]);
}
}
}
int ans = INF;
for(i = ; i <= n ; i++)
ans = min(ans,dp[(<<n)-][i]);
cout<<ans<<endl;
}
}ac;
char vir[],re[];
int main()
{
int n,m,i;
ac.init();
while(scanf("%d%d",&n,&m)&&n&&m)
{
ac.reset();
for(i = ; i <= n ;i++)
{
scanf("%s",re);
ac.insert(re,i);
}
while(m--)
{
scanf("%s",vir);
ac.insert(vir,-);
}
ac.construct();
ac.find_dis(n);
ac.work(n);
}
return ;
}

hdu3247Resource Archiver(ac自动机+spfa)的更多相关文章

  1. HDU3247 Resource Archiver (AC自动机+spfa+状压DP)

    Great! Your new software is almost finished! The only thing left to do is archiving all your n resou ...

  2. hdu3247Resource Archiver (AC自动机+最短路+状压dp)

    Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submis ...

  3. 【hdu3247-Resource Archiver】位压DP+AC自动机+SPFA

    题意:给定n个文本串,m个病毒串,文本串重叠部分可以合并,但合并后不能含有病毒串,问所有文本串合并后最短多长. (2 <= n <= 10, 1 <= m <= 1000) 题 ...

  4. hdu_3247_Resource Archiver(AC自动机+bfs+TSP)

    题目链接:hdu_3247_Resource Archiver 题意: 有n个资源串,m个病毒串,现在要将所有的资源串整合到一个串内,并且这个串不能包括病毒串,问最短的串长为多少 题解: 将资源串和病 ...

  5. HDU3247 Resource Archiver —— AC自动机 + BFS最短路 + 状压DP

    题目链接:https://vjudge.net/problem/HDU-3247 Resource Archiver Time Limit: 20000/10000 MS (Java/Others)  ...

  6. HDU - 3247 Resource Archiver (AC自动机,状压dp)

    \(\quad\)Great! Your new software is almost finished! The only thing left to do is archiving all you ...

  7. HDU 3247 Resource Archiver (AC自动机+BFS+状压DP)

    题意:给定 n 个文本串,m个病毒串,文本串重叠部分可以合并,但合并后不能含有病毒串,问所有文本串合并后最短多长. 析:先把所有的文本串和病毒都插入到AC自动机上,不过标记不一样,可以给病毒标记-1, ...

  8. 【HDU3247】 Resource Archiver(DP+AC自动机+最短路)

    Resource Archiver Time Limit: 10000MS   Memory Limit: 100000KB   64bit IO Format: %I64d & %I64u ...

  9. HDU-3247 Resource Archiver(AC自动机+BFS)

    Description Great! Your new software is almost finished! The only thing left to do is archiving all ...

随机推荐

  1. P1026 统计单词个数

    题意 给出一段字符串和一个字典,把字符串划分为n个连续的子串,求一种最优的划分方式使字符串所含单词数最大.(详见NOIp2001) 思路 这个题是一个很典型的线性dp,难点主要在预处理上. 理解题意后 ...

  2. C# DataGrid合并单元格

    1.栏位枚举 private enum DataGridColumn { ROWNUM = , EMPID, EMPNAME, SEX, SALARY, ADRRESS, PHONE, TEL, PO ...

  3. tableView主从表在storyboard连线是 Selcetion Segue和Accessory Action的区别

    当按住Ctorl这样连线时会出现,当选择Selection Segue下面的push时,点击cell的任何位置都会跳转到下一个tableView,当选择Accessory Action的下面的push ...

  4. sql 时间差

    select * from Tickets where ( case when UnloadTime is null then datediff(hh,LoadTime,getdate()) else ...

  5. lua语言三则特性

    pack和unpack 对于一个函数, 要将其入参转换为一个表, 则pack函数合适. 对于一个表要将其转换为 一个函数的入参, 则 lua原生提供的 unpack函数可以实现. do arrayDa ...

  6. PHP Apache服务配置

    第一步:在C:\Windows\System32\drivers\etc中找到hosts配置服务 127.0.0.1 localhost 127.0.0.1 www.psq.com 保存即可 第二步: ...

  7. [转] java集合详解

    结合框架体系应该最重要的是如何灵活利用三种接口,set,map,list,他们如何遍历,各有什么特征,怎么样去处理,这是关键,在这个基础上再去掌握在什么场合用什么类型的接口.比如说list和set,s ...

  8. .net程序员的学习计划

    .net程序员的学习计划 与其说是计划,不如说是抄来的课程表.基于最近老大要求写一份一年的职业规划.我是一个向来没什么规划的人,不是职场规划,就连平时的规划都没有,基本上就是有什么任务就去完成.回想起 ...

  9. for循环使用详解(c语言版)

    说明:c语言的很多语法部分都和JAVA,AS等相同 特别是for的用法. c语言中的for循环语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况 ...

  10. 使用AppCan实现分享网站功能

    使用AppCan实现分享网站功能 昨天我们实现了最基本的文字分享功能,今天呢,我们来实现基本的分享网站功能: 微信指引部分这里不再复述,具体请参见:http://newdocx.appcan.cn/i ...